JSON output
This commit is contained in:
@@ -75,6 +75,9 @@ garbage collection period in number of refresh. default is 50.
|
||||
\fB-P\fP
|
||||
Show only processes with the specified pid(s).
|
||||
.TP
|
||||
\fB-j\fP
|
||||
Output in JSON format.
|
||||
.TP
|
||||
\fB-f\fP
|
||||
EXPERIMENTAL: specify string pcap filter (like tcpdump). This may be removed or changed in a future version.
|
||||
.TP
|
||||
|
||||
71
src/cui.cpp
71
src/cui.cpp
@@ -49,6 +49,8 @@ extern int viewMode;
|
||||
extern bool showcommandline;
|
||||
extern bool showBasename;
|
||||
|
||||
extern bool output_json;
|
||||
|
||||
extern unsigned refreshlimit;
|
||||
extern unsigned refreshcount;
|
||||
|
||||
@@ -90,6 +92,7 @@ public:
|
||||
|
||||
void show(int row, unsigned int proglen, unsigned int devlen);
|
||||
void log();
|
||||
void json();
|
||||
|
||||
double sent_value;
|
||||
double recv_value;
|
||||
@@ -232,6 +235,48 @@ void Line::log() {
|
||||
<< recv_value << std::endl;
|
||||
}
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
std::string escape_json(const std::string &s) {
|
||||
std::ostringstream o;
|
||||
for (auto c = s.cbegin(); c != s.cend(); c++) {
|
||||
switch (*c) {
|
||||
case '"': o << "\\\""; break;
|
||||
case '\\': o << "\\\\"; break;
|
||||
case '\b': o << "\\b"; break;
|
||||
case '\f': o << "\\f"; break;
|
||||
case '\n': o << "\\n"; break;
|
||||
case '\r': o << "\\r"; break;
|
||||
case '\t': o << "\\t"; break;
|
||||
default:
|
||||
if ('\x00' <= *c && *c <= '\x1f') {
|
||||
o << "\\u"
|
||||
<< std::hex << std::setw(4) << std::setfill('0') << static_cast<int>(*c);
|
||||
} else {
|
||||
o << *c;
|
||||
}
|
||||
}
|
||||
}
|
||||
return o.str();
|
||||
}
|
||||
|
||||
void Line::json() {
|
||||
std::cout << "{";
|
||||
std::cout << "\"name\": \"" << escape_json(m_name) << "\"";
|
||||
std::cout << ", ";
|
||||
std::cout << "\"pid\": \"" << m_pid << "\"";
|
||||
std::cout << ", ";
|
||||
std::cout << "\"uid\": \"" << m_uid << "\"";
|
||||
std::cout << ", ";
|
||||
std::cout << "\"devicename\": \"" << devicename << "\"";
|
||||
std::cout << ", ";
|
||||
std::cout << "\"sent\": " << sent_value;
|
||||
std::cout << ", ";
|
||||
std::cout << "\"recv\": " << recv_value;
|
||||
std::cout << "}";
|
||||
}
|
||||
|
||||
|
||||
int get_devlen(Line *lines[], int nproc, int rows) {
|
||||
int devlen = MIN_COLUMN_WIDTH_DEV;
|
||||
int curlen;
|
||||
@@ -343,6 +388,28 @@ void show_trace(Line *lines[], int nproc) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char* get_iso8601_timestamp() {
|
||||
static char buffer[32];
|
||||
time_t now = time(NULL);
|
||||
struct tm *utc = gmtime(&now);
|
||||
strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%SZ", utc);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void show_json(Line *lines[], int nproc) {
|
||||
/* print them */
|
||||
std::cout << "{\"timestamp\": \""<< get_iso8601_timestamp() << "\", \"processes\": [";
|
||||
for (int i = 0; i < nproc; i++) {
|
||||
if(i>0){
|
||||
std::cout << ",";
|
||||
}
|
||||
lines[i]->json();
|
||||
delete lines[i];
|
||||
}
|
||||
std::cout << "]}"<< std::endl;
|
||||
}
|
||||
|
||||
void show_ncurses(Line *lines[], int nproc) {
|
||||
int rows; // number of terminal rows
|
||||
int cols; // number of terminal columns
|
||||
@@ -453,7 +520,9 @@ void do_refresh() {
|
||||
/* sort the accumulated lines */
|
||||
qsort(lines, nproc, sizeof(Line *), GreatestFirst);
|
||||
|
||||
if (tracemode || DEBUG)
|
||||
if (output_json)
|
||||
show_json(lines, nproc);
|
||||
else if (tracemode || DEBUG)
|
||||
show_trace(lines, nproc);
|
||||
else
|
||||
show_ncurses(lines, nproc);
|
||||
|
||||
14
src/main.cpp
14
src/main.cpp
@@ -69,6 +69,7 @@ static void help(bool iserror) {
|
||||
output << " b: display the program basename instead of the fullpath\n";
|
||||
output << " m: switch between total (kB, bytes, MB) and throughput (kB/s, "
|
||||
" MB/s, GB/s) mode\n";
|
||||
output << " j: json output\n";
|
||||
}
|
||||
|
||||
void quit_cb(int /* i */) {
|
||||
@@ -80,7 +81,7 @@ void quit_cb(int /* i */) {
|
||||
}
|
||||
|
||||
void forceExit(bool success, const char *msg, ...) {
|
||||
if ((!tracemode) && (!DEBUG)) {
|
||||
if ((!tracemode) && (!DEBUG) && (!output_json)) {
|
||||
exit_ui();
|
||||
}
|
||||
|
||||
@@ -141,7 +142,7 @@ void clean_up() {
|
||||
}
|
||||
|
||||
procclean();
|
||||
if ((!tracemode) && (!DEBUG))
|
||||
if ((!tracemode) && (!DEBUG) && (!output_json))
|
||||
exit_ui();
|
||||
}
|
||||
|
||||
@@ -153,7 +154,7 @@ int main(int argc, char **argv) {
|
||||
int garbage_collection_period = 50;
|
||||
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "Vhxtpsd:v:c:laf:Cbg:P:")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "Vhxtpsd:v:c:laf:Cbg:P:j")) != -1) {
|
||||
switch (opt) {
|
||||
case 'V':
|
||||
versiondisplay();
|
||||
@@ -204,6 +205,9 @@ int main(int argc, char **argv) {
|
||||
case 'P':
|
||||
pidsToWatch.insert((pid_t)atoi(optarg));
|
||||
break;
|
||||
case 'j':
|
||||
output_json = true;
|
||||
break;
|
||||
default:
|
||||
help(true);
|
||||
exit(EXIT_FAILURE);
|
||||
@@ -300,7 +304,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
struct dpargs *userdata = (dpargs *)malloc(sizeof(struct dpargs));
|
||||
|
||||
if ((!tracemode) && (!DEBUG)) {
|
||||
if ((!tracemode) && (!DEBUG) && (!output_json)) {
|
||||
init_ui();
|
||||
}
|
||||
|
||||
@@ -328,7 +332,7 @@ int main(int argc, char **argv) {
|
||||
time_t const now = ::time(NULL);
|
||||
if (last_refresh_time + refreshdelay <= now) {
|
||||
last_refresh_time = now;
|
||||
if ((!DEBUG) && (!tracemode)) {
|
||||
if ((!DEBUG) && (!tracemode) && (!output_json)) {
|
||||
// handle user input
|
||||
ui_tick();
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ bool showcommandline = false;
|
||||
bool showBasename = false;
|
||||
// viewMode: kb/s or total
|
||||
int viewMode = VIEWMODE_KBPS;
|
||||
bool output_json = false;
|
||||
const char version[] = " version " VERSION;
|
||||
timeval curtime;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user