You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by bc...@apache.org on 2012/05/05 01:18:30 UTC
[4/4] git commit: Converted the Perl program over to C++ and added
some features
Converted the Perl program over to C++ and added some features
Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/db91a420
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/db91a420
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/db91a420
Branch: refs/heads/master
Commit: db91a4204dfd343d55cff9d6776136102e58377c
Parents: 9ce0e71
Author: Bryan Call <br...@yahoo.com>
Authored: Thu May 3 15:26:00 2012 -0700
Committer: Bryan Call <br...@yahoo.com>
Committed: Thu May 3 15:26:00 2012 -0700
----------------------------------------------------------------------
contrib/tstop/src/stats.h | 305 ++++++++++++++++++++++++++++++++++
contrib/tstop/src/tstop.cc | 348 +++++++++++++++++++++++++++++++++++++++
2 files changed, 653 insertions(+), 0 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/db91a420/contrib/tstop/src/stats.h
----------------------------------------------------------------------
diff --git a/contrib/tstop/src/stats.h b/contrib/tstop/src/stats.h
new file mode 100644
index 0000000..97c63d2
--- /dev/null
+++ b/contrib/tstop/src/stats.h
@@ -0,0 +1,305 @@
+#include <curl/curl.h>
+#include <map>
+#include <string>
+
+using namespace std;
+
+struct LookupItem {
+ LookupItem(const char *s, const char *n, const int t): pretty(s), name(n), type(t) {}
+ LookupItem(const char *s, const char *n, const char *d, const int t): pretty(s), name(n), numerator(n), denominator(d), type(t) {}
+ const char *pretty;
+ const char *name;
+ const char *numerator;
+ const char *denominator;
+ int type;
+};
+extern size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream);
+extern char curl_error[CURL_ERROR_SIZE];
+extern string response;
+
+namespace constant {
+ const char global[] = "\"global\": {\n";
+ const char start[] = "\"proxy.process.";
+ const char seperator[] = "\": \"";
+ const char end[] = "\",\n";
+};
+
+//----------------------------------------------------------------------------
+class Stats {
+public:
+ Stats(const string &host) {
+ _host = host;
+ _stats = NULL;
+ _old_stats = NULL;
+ _absolute = false;
+ lookup_table.insert(make_pair("version", LookupItem("Version", "proxy.process.version.server.short", 1)));
+ lookup_table.insert(make_pair("disk_used", LookupItem("Disk Used", "proxy.process.cache.bytes_used", 1)));
+ lookup_table.insert(make_pair("disk_total", LookupItem("Disk Total", "proxy.process.cache.bytes_total", 1)));
+ lookup_table.insert(make_pair("ram_used", LookupItem("Ram Used", "proxy.process.cache.ram_cache.bytes_used", 1)));
+ lookup_table.insert(make_pair("ram_total", LookupItem("Ram Total", "proxy.process.cache.ram_cache.total_bytes", 1)));
+ lookup_table.insert(make_pair("lookups", LookupItem("Lookups", "proxy.process.http.cache_lookups", 2)));
+ lookup_table.insert(make_pair("cache_writes", LookupItem("Writes", "proxy.process.http.cache_writes", 2)));
+ lookup_table.insert(make_pair("cache_updates", LookupItem("Updates", "proxy.process.http.cache_updates", 2)));
+ lookup_table.insert(make_pair("cache_deletes", LookupItem("Deletes", "proxy.process.http.cache_deletes", 2)));
+ lookup_table.insert(make_pair("read_active", LookupItem("Read Active", "proxy.process.cache.read.active", 1)));
+ lookup_table.insert(make_pair("write_active", LookupItem("Writes Active", "proxy.process.cache.write.active", 1)));
+ lookup_table.insert(make_pair("update_active", LookupItem("Update Active", "proxy.process.cache.update.active", 1)));
+ lookup_table.insert(make_pair("entries", LookupItem("Entries", "proxy.process.cache.direntries.used", 1)));
+ lookup_table.insert(make_pair("avg_size", LookupItem("Avg Size", "disk_total", "entries", 3)));
+
+ lookup_table.insert(make_pair("client_req", LookupItem("Requests", "proxy.process.http.incoming_requests", 2)));
+ lookup_table.insert(make_pair("client_conn", LookupItem("New Conn", "proxy.process.http.total_client_connections", 2)));
+ lookup_table.insert(make_pair("client_req_conn", LookupItem("Req/Conn", "client_req", "client_conn", 3)));
+ lookup_table.insert(make_pair("client_curr_conn", LookupItem("Curr Conn", "proxy.process.http.current_client_connections", 1)));
+ lookup_table.insert(make_pair("client_actv_conn", LookupItem("Active Con", "proxy.process.http.current_active_client_connections", 1)));
+
+ lookup_table.insert(make_pair("server_req", LookupItem("Requests", "proxy.process.http.outgoing_requests", 2)));
+ lookup_table.insert(make_pair("server_conn", LookupItem("New Conn", "proxy.process.http.total_server_connections", 2)));
+ lookup_table.insert(make_pair("server_req_conn", LookupItem("Req/Conn", "server_req", "server_conn", 3)));
+ lookup_table.insert(make_pair("server_curr_conn", LookupItem("Curr Conn", "proxy.process.http.current_server_connections", 1)));
+
+
+ lookup_table.insert(make_pair("client_head", LookupItem("Head Bytes", "proxy.process.http.user_agent_response_header_total_size", 2)));
+ lookup_table.insert(make_pair("client_body", LookupItem("Body Bytes", "proxy.process.http.user_agent_response_document_total_size", 2)));
+ lookup_table.insert(make_pair("server_head", LookupItem("Head Bytes", "proxy.process.http.origin_server_response_header_total_size", 2)));
+ lookup_table.insert(make_pair("server_body", LookupItem("Body Bytes", "proxy.process.http.origin_server_response_document_total_size", 2)));
+
+ // not used directly
+ lookup_table.insert(make_pair("ram_hit", LookupItem("Ram Hit", "proxy.process.cache.ram_cache.hits", 2)));
+ lookup_table.insert(make_pair("ram_miss", LookupItem("Ram Misses", "proxy.process.cache.ram_cache.misses", 2)));
+
+
+
+ lookup_table.insert(make_pair("client_abort", LookupItem("Clnt Abort", "proxy.process.http.err_client_abort_count_stat", 2)));
+ lookup_table.insert(make_pair("conn_fail", LookupItem("Conn Fail", "proxy.process.http.err_connect_fail_count_stat", 2)));
+ lookup_table.insert(make_pair("abort", LookupItem("Abort", "proxy.process.http.transaction_counts.errors.aborts", 2)));
+ lookup_table.insert(make_pair("t_conn_fail", LookupItem("Conn Fail", "proxy.process.http.transaction_counts.errors.connect_failed", 2)));
+ lookup_table.insert(make_pair("other_err", LookupItem("Other Err", "proxy.process.http.transaction_counts.errors.other", 2)));
+ // percentage
+ lookup_table.insert(make_pair("ram_ratio", LookupItem("Ram Hit", "ram_hit", "ram_hit_miss", 4)));
+
+ // percetage of requests
+ lookup_table.insert(make_pair("fresh", LookupItem("Fresh", "proxy.process.http.transaction_counts.hit_fresh", 5)));
+ lookup_table.insert(make_pair("reval", LookupItem("Revalidate", "proxy.process.http.transaction_counts.hit_revalidated", 5)));
+ lookup_table.insert(make_pair("cold", LookupItem("Cold", "proxy.process.http.transaction_counts.miss_cold", 5)));
+ lookup_table.insert(make_pair("changed", LookupItem("Changed", "proxy.process.http.transaction_counts.miss_changed", 5)));
+ lookup_table.insert(make_pair("not", LookupItem("Not Cache", "proxy.process.http.transaction_counts.miss_not_cacheable", 5)));
+ lookup_table.insert(make_pair("no", LookupItem("No Cache", "proxy.process.http.transaction_counts.miss_client_no_cache", 5)));
+
+ lookup_table.insert(make_pair("fresh_time", LookupItem("Fresh (ms)", "proxy.process.http.transaction_totaltime.hit_fresh", "fresh", 8)));
+ lookup_table.insert(make_pair("reval_time", LookupItem("Reval (ms)", "proxy.process.http.transaction_totaltime.hit_revalidated", "reval", 8)));
+ lookup_table.insert(make_pair("cold_time", LookupItem("Cold (ms)", "proxy.process.http.transaction_totaltime.miss_cold", "cold", 8)));
+ lookup_table.insert(make_pair("changed_time", LookupItem("Chang (ms)", "proxy.process.http.transaction_totaltime.miss_changed", "changed", 8)));
+ lookup_table.insert(make_pair("not_time", LookupItem("Not (ms)", "proxy.process.http.transaction_totaltime.miss_not_cacheable", "not", 8)));
+ lookup_table.insert(make_pair("no_time", LookupItem("No (no)", "proxy.process.http.transaction_totaltime.miss_client_no_cache", "no", 8)));
+
+ lookup_table.insert(make_pair("get", LookupItem("GET", "proxy.process.http.get_requests", 5)));
+ lookup_table.insert(make_pair("head", LookupItem("HEAD", "proxy.process.http.head_requests", 5)));
+ lookup_table.insert(make_pair("post", LookupItem("POST", "proxy.process.http.post_requests", 5)));
+ lookup_table.insert(make_pair("2xx", LookupItem("2xx", "proxy.process.http.2xx_responses", 5)));
+ lookup_table.insert(make_pair("3xx", LookupItem("3xx", "proxy.process.http.3xx_responses", 5)));
+ lookup_table.insert(make_pair("4xx", LookupItem("4xx", "proxy.process.http.4xx_responses", 5)));
+ lookup_table.insert(make_pair("5xx", LookupItem("5xx", "proxy.process.http.5xx_responses", 5)));
+
+ lookup_table.insert(make_pair("200", LookupItem("200", "proxy.process.http.200_responses", 5)));
+ lookup_table.insert(make_pair("206", LookupItem("206", "proxy.process.http.206_responses", 5)));
+ lookup_table.insert(make_pair("301", LookupItem("301", "proxy.process.http.301_responses", 5)));
+ lookup_table.insert(make_pair("302", LookupItem("302", "proxy.process.http.302_responses", 5)));
+ lookup_table.insert(make_pair("304", LookupItem("304", "proxy.process.http.304_responses", 5)));
+ lookup_table.insert(make_pair("404", LookupItem("404", "proxy.process.http.404_responses", 5)));
+ lookup_table.insert(make_pair("502", LookupItem("502", "proxy.process.http.502_responses", 5)));
+
+ lookup_table.insert(make_pair("s_100", LookupItem("100 B", "proxy.process.http.response_document_size_100", 5)));
+ lookup_table.insert(make_pair("s_1k", LookupItem("1 KB", "proxy.process.http.response_document_size_1K", 5)));
+ lookup_table.insert(make_pair("s_3k", LookupItem("3 KB", "proxy.process.http.response_document_size_3K", 5)));
+ lookup_table.insert(make_pair("s_5k", LookupItem("5 KB", "proxy.process.http.response_document_size_5K", 5)));
+ lookup_table.insert(make_pair("s_10k", LookupItem("10 KB", "proxy.process.http.response_document_size_10K", 5)));
+ lookup_table.insert(make_pair("s_1m", LookupItem("1 MB", "proxy.process.http.response_document_size_1M", 5)));
+ lookup_table.insert(make_pair("s_>1m", LookupItem("> 1 MB", "proxy.process.http.response_document_size_inf", 5)));
+
+
+ // sum together
+ lookup_table.insert(make_pair("ram_hit_miss", LookupItem("Ram Hit+Miss", "ram_hit", "ram_miss", 6)));
+ lookup_table.insert(make_pair("client_net", LookupItem("Net (bits)", "client_head", "client_body", 7)));
+ lookup_table.insert(make_pair("client_size", LookupItem("Total Size", "client_head", "client_body", 6)));
+ lookup_table.insert(make_pair("client_avg_size", LookupItem("Avg Size", "client_size", "client_req", 3)));
+
+ lookup_table.insert(make_pair("server_net", LookupItem("Net (bits)", "server_head", "server_body", 7)));
+ lookup_table.insert(make_pair("server_size", LookupItem("Total Size", "server_head", "server_body", 6)));
+ lookup_table.insert(make_pair("server_avg_size", LookupItem("Avg Size", "server_size", "server_req", 3)));
+
+
+ lookup_table.insert(make_pair("total_time", LookupItem("Total Time", "proxy.process.http.total_transactions_time", 2)));
+ lookup_table.insert(make_pair("client_req_time", LookupItem("Resp (ms)", "total_time", "client_req", 3)));
+ }
+
+ void getStats() {
+ CURL *curl;
+ CURLcode res;
+
+ if (_old_stats != NULL) {
+ delete _old_stats;
+ _old_stats = NULL;
+ }
+ _old_stats = _stats;
+ _stats = new map<string, string>;
+
+ curl = curl_easy_init();
+ if (curl) {
+ string url = "http://" + _host + "/_stats";
+ curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
+ curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_error);
+
+ // update time
+ _old_time = _now;
+ gettimeofday(&_time, NULL);
+ _now = _time.tv_sec + (double)_time.tv_usec / 1000000;
+ _time_diff = _now - _old_time;
+
+ res = curl_easy_perform(curl);
+ cout << curl_error << endl;
+ assert(res == 0);
+ /* always cleanup */
+ curl_easy_cleanup(curl);
+
+ // parse
+ parseResponse(response);
+ }
+ }
+
+ int64_t getValue(const string &key, const map<string, string> *stats) const {
+ map<string, string>::const_iterator stats_it = stats->find(key);
+ assert(stats_it != stats->end());
+ int64_t value = atoll(stats_it->second.c_str());
+ return value;
+ }
+
+ void getStat(const string &key, double &value, int overrideType = 0) {
+ string strtmp;
+ int typetmp;
+ getStat(key, value, strtmp, typetmp, overrideType);
+ }
+
+
+ void getStat(const string &key, string &value) {
+ map<string, LookupItem>::const_iterator lookup_it = lookup_table.find(key);
+ assert(lookup_it != lookup_table.end());
+ const LookupItem &item = lookup_it->second;
+
+ map<string, string>::const_iterator stats_it = _stats->find(item.name);
+ assert(stats_it != _stats->end());
+ value = stats_it->second.c_str();
+ }
+
+ void getStat(const string &key, double &value, string &prettyName, int &type, int overrideType = 0) {
+ map<string, LookupItem>::const_iterator lookup_it = lookup_table.find(key);
+ assert(lookup_it != lookup_table.end());
+ const LookupItem &item = lookup_it->second;
+ prettyName = item.pretty;
+ if (overrideType != 0)
+ type = overrideType;
+ else
+ type = item.type;
+
+ if (type == 1 || type == 2 || type == 5 || type == 8) {
+ value = getValue(item.name, _stats);
+ if (key == "total_time") {
+ value = value / 10000000;
+ }
+
+ if ((type == 2 || type == 5 || type == 8) && _old_stats != NULL && _absolute == false) {
+ double old = getValue(item.name, _old_stats);
+ if (key == "total_time") {
+ old = old / 10000000;
+ }
+ value = (value - old) / _time_diff;
+ }
+ } else if (type == 3 || type == 4) {
+ double numerator;
+ double denominator;
+ getStat(item.numerator, numerator);
+ getStat(item.denominator, denominator);
+ if (denominator == 0)
+ value = 0;
+ else
+ value = numerator / denominator;
+ if (type == 4) {
+ value *= 100;
+ }
+ } else if (type == 6 || type == 7) {
+ double numerator;
+ double denominator;
+ getStat(item.numerator, numerator, 2);
+ getStat(item.denominator, denominator, 2);
+ value = numerator + denominator;
+ if (type == 7)
+ value *= 8;
+ }
+
+ if (type == 8) {
+ double denominator;
+ getStat(item.denominator, denominator, 2);
+ if (denominator == 0)
+ value = 0;
+ else
+ value = value / denominator * 1000;
+ }
+
+ if (type == 5) {
+ double denominator;
+ getStat("client_req", denominator);
+ value = value / denominator * 100;
+ }
+
+
+ }
+
+ bool toggleAbsolute() {
+ if (_absolute == true)
+ _absolute = false;
+ else
+ _absolute = true;
+
+ return _absolute;
+ }
+
+ void parseResponse(const string &response) {
+ // move past global
+ size_t pos = response.find(constant::global);
+ pos += sizeof(constant::global) - 1;
+
+ // find parts of the line
+ while (1) {
+ size_t start = response.find(constant::start, pos);
+ size_t seperator = response.find(constant::seperator, pos);
+ size_t end = response.find(constant::end, pos);
+
+ if (start == string::npos || seperator == string::npos || end == string::npos)
+ return;
+
+ //cout << constant::start << " " << start << endl;
+ //cout << constant::seperator << " " << seperator << endl;
+ //cout << constant::end << " " << end << endl;
+
+ string key = response.substr(start + 1, seperator - start - 1);
+ string value = response.substr(seperator + sizeof(constant::seperator) - 1, end - seperator - sizeof(constant::seperator) + 1);
+
+ (*_stats)[key] = value;
+ //cout << "key " << key << " " << "value " << value << endl;
+ pos = end + sizeof(constant::end) - 1;
+ //cout << "pos: " << pos << endl;
+ }
+ }
+
+private:
+ map<string, string> *_stats;
+ map<string, string> *_old_stats;
+ map<string, LookupItem> lookup_table;
+ string _host;
+ double _old_time;
+ double _now;
+ double _time_diff;
+ struct timeval _time;
+ bool _absolute;
+};
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/db91a420/contrib/tstop/src/tstop.cc
----------------------------------------------------------------------
diff --git a/contrib/tstop/src/tstop.cc b/contrib/tstop/src/tstop.cc
new file mode 100644
index 0000000..e1556f0
--- /dev/null
+++ b/contrib/tstop/src/tstop.cc
@@ -0,0 +1,348 @@
+#include <ncurses.h>
+#include <list>
+#include <string.h>
+#include <string>
+#include <iostream>
+#include <assert.h>
+#include <map>
+#include <stdlib.h>
+#include "stats.h"
+#include <unistd.h>
+#include <getopt.h>
+
+using namespace std;
+char curl_error[CURL_ERROR_SIZE];
+string response;
+
+
+namespace colorPair {
+ const short red = 1;
+ const short yellow = 2;
+ const short green = 3;
+ const short blue = 4;
+ const short black = 5;
+ const short grey = 6;
+ const short cyan = 7;
+ const short border = 8;
+};
+
+
+//----------------------------------------------------------------------------
+int printGraphLabels(int x, int y, int width, list<const char*> lables) {
+ char buffer[256];
+ for (list<const char*>::const_iterator it = lables.begin();
+ it != lables.end(); ++it) {
+
+ char *pos = buffer;
+ pos += snprintf(buffer, 256, "%7s [", *it);
+ memset(pos, ' ', width);
+ pos += width - 1;
+
+ strncat(pos, "]", buffer - pos);
+
+ mvprintw(y++, x, buffer);
+ }
+
+ // mvprintw(x, y,
+}
+
+
+//----------------------------------------------------------------------------
+void prettyPrint(const int x, const int y, const double number, const int type) {
+ char buffer[32];
+ char exp = ' ';
+ double my_number = number;
+ short color;
+ if (number > 1000000000000LL) {
+ my_number = number / 1000000000000;
+ exp = 'T';
+ color = colorPair::red;
+ } else if (number > 1000000000) {
+ my_number = number / 1000000000;
+ exp = 'G';
+ color = colorPair::red;
+ } else if (number > 1000000) {
+ my_number = number / 1000000;
+ exp = 'M';
+ color = colorPair::yellow;
+ } else if (number > 1000) {
+ my_number = number / 1000;
+ exp = 'K';
+ color = colorPair::cyan;
+ } else if (my_number <= .09) {
+ color = colorPair::grey;
+ } else {
+ color = colorPair::green;
+ }
+
+ if (type == 4 || type == 5) {
+ if (number > 90) {
+ color = colorPair::red;
+ } else if (number > 80) {
+ color = colorPair::yellow;
+ } else if (number > 50) {
+ color = colorPair::blue;
+ } else if (my_number <= .09) {
+ color = colorPair::grey;
+ } else {
+ color = colorPair::green;
+ }
+ snprintf(buffer, sizeof(buffer), "%6.1f%%%%", (double)my_number);
+ } else
+ snprintf(buffer, sizeof(buffer), "%6.1f%c", (double)my_number, exp);
+ attron(COLOR_PAIR(color));
+ attron(A_BOLD);
+ mvprintw(y, x, buffer);
+ attroff(COLOR_PAIR(color));
+ attroff(A_BOLD);
+}
+
+//----------------------------------------------------------------------------
+void makeTable(const int x, const int y, const list<string> &items, Stats &stats) {
+ int my_y = y;
+
+ for (list<string>::const_iterator it = items.begin(); it != items.end(); ++it) {
+ string prettyName;
+ double value;
+ int type;
+
+ stats.getStat(*it, value, prettyName, type);
+ mvprintw(my_y, x, prettyName.c_str());
+ prettyPrint(x + 10, my_y++, value, type);
+ }
+}
+
+//----------------------------------------------------------------------------
+size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream)
+{
+ response.append((char*)ptr, size * nmemb);
+ //cout << "appending: " << size * nmemb << endl;
+ //int written = fwrite(ptr, size, nmemb, (FILE *)stream);
+ return size * nmemb;
+}
+
+//----------------------------------------------------------------------------
+void help(const string &host, const string &version) {
+
+ timeout(1000);
+
+ while(1) {
+ clear();
+ time_t now = time(NULL);
+ struct tm *nowtm = localtime(&now);
+ char timeBuf[32];
+ strftime(timeBuf, sizeof(timeBuf), "%H:%M:%S", nowtm);
+
+ //clear();
+ attron(A_BOLD); mvprintw(0, 0, "Overview:"); attroff(A_BOLD);
+ mvprintw(1, 0, "tstop is a top like program for Apache Traffic Server (ATS). There is a lot of statistical information gathered by ATS. This program tries to show some of the more important stats and gives a good overview of what the proxy server is doing. Hopefully this can be used as a tool to diagnosing the proxy server is there are problems.");
+
+ attron(A_BOLD); mvprintw(7, 0, "Definitions:"); attroff(A_BOLD);
+ mvprintw(8, 0, "Fresh => Requests that were servered by fresh entries in cache");
+ mvprintw(9, 0, "Revalidate => Requests that contacted the origin to verify if still valid");
+ mvprintw(10, 0, "Cold => Requests that were not in cache at all");
+ mvprintw(11, 0, "Changed => Requests that required entries in cache to be updated");
+ mvprintw(12, 0, "Changed => Requests that can't be cached for some reason");
+ mvprintw(12, 0, "No Cache => Requests that the client sent Cache-Control: no-cache header");
+
+ attron(COLOR_PAIR(colorPair::border));
+ attron(A_BOLD);
+ mvprintw(23, 0, "%s - %.12s - %.12s (b)ack ", timeBuf, version.c_str(), host.c_str());
+ attroff(COLOR_PAIR(colorPair::border));
+ attroff(A_BOLD);
+ refresh();
+ int x = getch();
+ if (x == 'b')
+ break;
+ }
+}
+
+void usage(char **argv) {
+ fprintf(stderr, "Usage: %s [-s seconds] hostname|hostname:port\n", argv[0]);
+ exit(1);
+}
+
+
+//----------------------------------------------------------------------------
+int main(int argc, char **argv)
+{
+ int sleep_time = 5000;
+ bool absolute = false;
+ int opt;
+ while ((opt = getopt(argc, argv, "s:")) != -1) {
+ switch(opt) {
+ case 's':
+ sleep_time = atoi(optarg) * 1000;
+ break;
+ default:
+ usage(argv);
+ }
+ }
+
+ if (optind >= argc) {
+ fprintf(stderr, "Error: missing hostname on command line\n");
+ usage(argv);
+ }
+
+ string host = argv[optind];
+ Stats stats(host);
+
+ //cout << response;
+ //return 1;
+
+ initscr();
+ curs_set(0);
+
+
+ start_color(); /* Start color functionality */
+
+ init_pair(colorPair::red, COLOR_RED, COLOR_BLACK);
+ init_pair(colorPair::yellow, COLOR_YELLOW, COLOR_BLACK);
+ init_pair(colorPair::grey, COLOR_BLACK, COLOR_BLACK);
+ init_pair(colorPair::green, COLOR_GREEN, COLOR_BLACK);
+ init_pair(colorPair::blue, COLOR_BLUE, COLOR_BLACK);
+ init_pair(colorPair::cyan, COLOR_CYAN, COLOR_BLACK);
+ init_pair(colorPair::border, COLOR_WHITE, COLOR_BLUE);
+ // mvchgat(0, 0, -1, A_BLINK, 1, NULL);
+
+ stats.getStats();
+ while(1) {
+ attron(COLOR_PAIR(colorPair::border));
+ attron(A_BOLD);
+ for (int i = 0; i <= 22; ++i) {
+ mvprintw(i, 39, " ");
+ }
+ string version;
+ time_t now = time(NULL);
+ struct tm *nowtm = localtime(&now);
+ char timeBuf[32];
+ strftime(timeBuf, sizeof(timeBuf), "%H:%M:%S", nowtm);
+ stats.getStat("version", version);
+ mvprintw(0, 0, " CACHE INFORMATION ");
+ mvprintw(0, 40, " CLIENT REQUEST & RESPONSE ");
+ mvprintw(16, 0, " CLIENT ");
+ mvprintw(16, 40, " ORIGIN SERVER ");
+ mvprintw(23, 0, "%s - %.12s - %.12s (q)uit (h)elp (%c)bsolute ", timeBuf, version.c_str(), host.c_str(), absolute ? 'A' : 'a');
+ attroff(COLOR_PAIR(colorPair::border));
+ attroff(A_BOLD);
+
+ list<string> cache1;
+ cache1.push_back("disk_used");
+ cache1.push_back("disk_total");
+ cache1.push_back("ram_used");
+ cache1.push_back("ram_total");
+ cache1.push_back("lookups");
+ cache1.push_back("cache_writes");
+ cache1.push_back("cache_updates");
+ cache1.push_back("cache_deletes");
+ cache1.push_back("read_active");
+ cache1.push_back("write_active");
+ cache1.push_back("update_active");
+ cache1.push_back("entries");
+ cache1.push_back("avg_size");
+ makeTable(0, 1, cache1, stats);
+
+
+ list<string> cache2;
+ cache2.push_back("ram_ratio");
+ cache2.push_back("fresh");
+ cache2.push_back("reval");
+ cache2.push_back("cold");
+ cache2.push_back("changed");
+ cache2.push_back("not");
+ cache2.push_back("no");
+ cache2.push_back("fresh_time");
+ cache2.push_back("reval_time");
+ cache2.push_back("cold_time");
+ cache2.push_back("changed_time");
+ cache2.push_back("not_time");
+ cache2.push_back("no_time");
+ makeTable(21, 1, cache2, stats);
+
+ list<string> response1;
+ response1.push_back("get");
+ response1.push_back("head");
+ response1.push_back("post");
+ response1.push_back("2xx");
+ response1.push_back("3xx");
+ response1.push_back("4xx");
+ response1.push_back("5xx");
+ //response1.push_back("response_abort");
+ response1.push_back("conn_fail");
+ response1.push_back("other_err");
+ response1.push_back("abort");
+ makeTable(41, 1, response1, stats);
+
+
+ list<string> response2;
+ response2.push_back("200");
+ response2.push_back("206");
+ response2.push_back("301");
+ response2.push_back("302");
+ response2.push_back("304");
+ response2.push_back("404");
+ response2.push_back("502");
+ response2.push_back("s_100");
+ response2.push_back("s_1k");
+ response2.push_back("s_3k");
+ response2.push_back("s_5k");
+ response2.push_back("s_10k");
+ response2.push_back("s_1m");
+ response2.push_back("s_>1m");
+ makeTable(62, 1, response2, stats);
+
+ list<string> client1;
+ client1.push_back("client_req");
+ client1.push_back("client_req_conn");
+ client1.push_back("client_conn");
+ client1.push_back("client_curr_conn");
+ client1.push_back("client_actv_conn");
+ makeTable(0, 17, client1, stats);
+
+
+ list<string> client2;
+ client2.push_back("client_head");
+ client2.push_back("client_body");
+ client2.push_back("client_avg_size");
+ client2.push_back("client_net");
+ client2.push_back("client_req_time");
+ makeTable(21, 17, client2, stats);
+
+ list<string> server1;
+ server1.push_back("server_req");
+ server1.push_back("server_req_conn");
+ server1.push_back("server_conn");
+ server1.push_back("server_curr_conn");
+ makeTable(41, 17, server1, stats);
+
+
+ list<string> server2;
+ server2.push_back("server_head");
+ server2.push_back("server_body");
+ server2.push_back("server_avg_size");
+ server2.push_back("server_net");
+ makeTable(62, 17, server2, stats);
+
+
+ curs_set(0);
+ refresh();
+// sleep(5);
+ timeout(sleep_time);
+ loop:
+ int x = getch();
+ if (x == 'q')
+ break;
+ if (x == 'h') {
+ help(host, version);
+ }
+ if (x == 'a') {
+ absolute = stats.toggleAbsolute();
+ }
+ if (x == -1)
+ stats.getStats();
+ clear();
+ }
+ endwin();
+
+ return 0;
+}