Commit 6475d0a9 authored by Daan Vreeken's avatar Daan Vreeken
Browse files

o Make the amount of time that is logged for a plot adjustable with new

  command line option '--history [seconds]'. The default is still 60
  seconds.
o Add a command line option '--interval [seconds]' to set the sample
  interval. The default sample interval without the options remains 0.2
  seconds as before.
o Add '--host [IP address or hostname]' command line option to view traces
  on a remote machine.
o Add '--port [remote port number]' command line option to specify the port
  number of the trace server to connect to.
o Add usage() function to inform user of possible optins.
o Keep track of the lowest and highest values in a plot and adjust the y
  range to be just over min and max so that all samples will fit within the
  plot, without the highest and lowest values dissapearing under the borders
  of the plot.

	modified:   common/trace/trace_view.c
parent 2f2ff187
......@@ -26,12 +26,15 @@
#include <string.h>
#include <math.h>
#include <time.h>
#include <err.h>
#include <trace/trace.h>
time_t starttime;
#define VAL_BUFLEN (60 * 5)
int val_buflen;
//#define VAL_BUFLEN (60 * 5)
FILE *fdplot = NULL;
int doplot = 0;
......@@ -39,19 +42,30 @@ struct trace_view {
struct trace *trace;
char *tmpfilename;
FILE *fdtmp;
struct trace_value value[VAL_BUFLEN];
struct trace_value *value;
int bufpos;
};
struct trace_view *traces;
float samp_min, samp_max;
static void add_to_range(float val)
{
if (val < samp_min)
samp_min = val;
if (val > samp_max)
samp_max = val;
}
void plot_values(struct trace_view *traces, int nr_traces)
{
int i;
int bufpos = (traces[0].bufpos+VAL_BUFLEN-1) % VAL_BUFLEN;
int bufpos = (traces[0].bufpos + val_buflen - 1) % val_buflen;
long long now = traces[0].value[bufpos].t.tv_sec;
long nown = traces[0].value[bufpos].t.tv_nsec;
float range, range_low, range_high;
fprintf(fdplot, "plot ");
......@@ -65,6 +79,19 @@ void plot_values(struct trace_view *traces, int nr_traces)
"");
}
fprintf(fdplot, "\n");
// Calculate an y range that will fit all samples, plus a tiny bit
// more so the lowest/highest values are still visible at the edges of
// the plot.
//printf("sample range: %f, %f\n", samp_min, samp_max);
range = samp_max - samp_min;
if (range == 0.0)
range = 0.1;
range_low = samp_min - range * 0.02;
range_high = samp_max + range * 0.02;
fprintf(fdplot, "set yrange [%e:%e]\n", range_low, range_high);
fflush(NULL);
return;
......@@ -77,34 +104,42 @@ static void print_value(FILE *fd,
case TRACE_VALUE_TYPE_FLOAT:
fprintf(fd, "%ld.%09ld %e\n",
value->t.tv_sec, value->t.tv_nsec, value->value.f);
add_to_range(value->value.f);
break;
case TRACE_VALUE_TYPE_BOOL:
fprintf(fd, "%ld.%09ld %d\n",
value->t.tv_sec, value->t.tv_nsec, value->value.b);
add_to_range(value->value.b);
break;
case TRACE_VALUE_TYPE_UINT8:
fprintf(fd, "%ld.%09ld %u\n",
value->t.tv_sec, value->t.tv_nsec, value->value.u8);
add_to_range(value->value.u8);
break;
case TRACE_VALUE_TYPE_UINT16:
fprintf(fd, "%ld.%09ld %u\n",
value->t.tv_sec, value->t.tv_nsec, value->value.u16);
add_to_range(value->value.u16);
break;
case TRACE_VALUE_TYPE_UINT32:
fprintf(fd, "%ld.%09ld %u\n",
value->t.tv_sec, value->t.tv_nsec, value->value.u32);
add_to_range(value->value.u32);
break;
case TRACE_VALUE_TYPE_SINT8:
fprintf(fd, "%ld.%09ld %d\n",
value->t.tv_sec, value->t.tv_nsec, value->value.s8);
add_to_range(value->value.s8);
break;
case TRACE_VALUE_TYPE_SINT16:
fprintf(fd, "%ld.%09ld %d\n",
value->t.tv_sec, value->t.tv_nsec, value->value.s16);
add_to_range(value->value.s16);
break;
case TRACE_VALUE_TYPE_SINT32:
fprintf(fd, "%ld.%09ld %d\n",
value->t.tv_sec, value->t.tv_nsec, value->value.s32);
add_to_range(value->value.s32);
break;
}
}
......@@ -120,8 +155,9 @@ static void handler_value(struct trace *trace,
view->value[view->bufpos] = *value;
freopen(NULL, "w", view->fdtmp);
for (i = view->bufpos + 1; i < VAL_BUFLEN; i++) {
if (!view->value[i].t.tv_sec)
for (i = view->bufpos + 1; i < val_buflen; i++) {
if ((!view->value[i].t.tv_sec) ||
(view->value[i].t.tv_sec == 1))
continue;
print_value(view->fdtmp, trace, &view->value[i]);
......@@ -136,55 +172,159 @@ static void handler_value(struct trace *trace,
view->bufpos++;
view->bufpos %= VAL_BUFLEN;
view->bufpos %= val_buflen;
doplot++;
}
static void usage(char *progname)
{
fprintf(stderr, "usage: %s [options] [one or more trace names]\n"
"available options:\n"
" --host [hostname] set the name of the host to connect to\n"
" --port [port#] set the remote port number to connect "
"to\n"
" --interval [seconds] set the sample interval\n",
" --history [seconds] set the length of the plot\n",
progname);
exit(1);
}
int main(int argc, char **argv)
{
int i, ret = 0;
struct timespec t_int;
struct trace_view *t;
double interval, history;
char *host;
int trace_nr, i, port, ret = 0;
starttime = time(NULL);
host = "localhost";
port = 10000;
if (argc < 2)
usage(argv[0]);
history = 60.0;
interval = 0.2;
traces = calloc(sizeof(struct trace_view), argc - 1);
trace_nr = 0;
for (i = 0; i < argc - 1; i++) {
char *tracename = argv[i+1];
struct trace_pkt *pkt;
struct timespec t_int;
int fdmkstemp;
printf("%s\n", tracename);
traces[i].trace = trace_open("localhost", 10000);
if (!traces[i].trace) {
printf("open trace failed\n");
if (strcmp(tracename, "--host") == 0) {
if (i >= argc - 2)
errx(1, "missing hostname");
i++;
host = argv[i + 1];
fprintf(stderr, "Setting remote host to '%s'\n",
host);
continue;
}
if (strcmp(tracename, "--port") == 0) {
if (i >= argc - 2)
errx(1, "missing port number");
i++;
port = atoi(argv[i + 1]);
fprintf(stderr, "Setting remote port to %d\n", port);
continue;
}
if (strcmp(tracename, "--interval") == 0) {
if (i >= argc - 2)
errx(1, "missing interval argument");
i++;
interval = atof(argv[i + 1]);
fprintf(stderr, "Setting sample interval %fs\n",
interval);
continue;
}
if (strcmp(tracename, "--history") == 0) {
if (i >= argc - 2)
errx(1, "missing history argument");
i++;
history = atof(argv[i + 1]);
fprintf(stderr, "Setting history to %fs\n", history);
continue;
}
fprintf(stderr, "Adding trace '%s'\n", tracename);
t = &traces[trace_nr];
t->trace = trace_open(host, port);
if (!t->trace) {
fprintf(stderr, "opening trace on %s:%d failed\n",
host, port);
return 1;
}
traces[i].trace->private = &traces[i];
trace_name_set(traces[i].trace, tracename);
t->trace->private = &traces[trace_nr];
trace_name_set(t->trace, tracename);
traces[i].tmpfilename = malloc(100);
sprintf(traces[i].tmpfilename, "/tmp/trace_view_XXXXXX");
fdmkstemp = mkstemp(traces[i].tmpfilename);
t->tmpfilename = malloc(100);
sprintf(t->tmpfilename,
"/tmp/trace_view_XXXXXX");
fdmkstemp = mkstemp(t->tmpfilename);
printf("Going to use %s temp file for '%s' data\n",
traces[i].tmpfilename, tracename);
traces[i].fdtmp = fdopen(fdmkstemp, "w");
if (traces[i].fdtmp == NULL) {
t->tmpfilename, tracename);
t->fdtmp = fdopen(fdmkstemp, "w");
if (t->fdtmp == NULL) {
perror("fopen() failed");
return 1;
}
t_int.tv_sec = 0;
t_int.tv_nsec = 200*1000*1000;
t->trace->handler_value = handler_value;
trace_nr++;
}
if (trace_nr == 0) {
// Only options, but no trace names..
fprintf(stderr, "Error: Need at least one trace name.\n\n");
usage(argv[0]);
}
// calculate buffer length & sample interval
if (interval <= 0.0)
errx(1, "invalid interval!");
if (history <= 0.0)
errx(1, "invalid history length!");
if (history < interval)
errx(1, "history length must be >= interval!");
t_int.tv_sec = floor(interval);
t_int.tv_nsec = (interval - t_int.tv_sec) * 1.0e9;
//t_int.tv_sec = 0;
//t_int.tv_nsec = 200 * 1000;
// set interval on all trace connections
for (i = 0; i < trace_nr; i++) {
struct trace_pkt *pkt;
t = &traces[i];
pkt = trace_packet_new();
trace_packet_interval_set(pkt,
&t_int, TRACE_INTERVAL_TYPE_INTERVAL);
trace_packet_write(traces[i].trace, pkt);
trace_packet_write(t->trace, pkt);
trace_packet_put(pkt);
}
traces[i].trace->handler_value = handler_value;
// allocate memory for enough samples
val_buflen = ceil(history / interval);
//printf("buflen=%d samples\n", val_buflen);
//printf("interval= %d.%09d\n", t_int.tv_sec, t_int.tv_nsec);
for (i = 0; i < trace_nr; i++) {
traces[i].value = calloc(val_buflen,
sizeof(struct trace_value));
if (traces[i].value == NULL)
errx(1, "out of memory!");
}
fdplot = popen("gnuplot -noraise", "w");
......@@ -195,24 +335,32 @@ int main(int argc, char **argv)
fprintf(fdplot, "set grid\n");
samp_min = +INFINITY;
samp_max = -INFINITY;
do {
fd_set fdrx;
int high = 0;
FD_ZERO(&fdrx);
for (i = 0; i < argc - 1; i++)
for (i = 0; i < trace_nr; i++) {
trace_fd_set(traces[i].trace, &fdrx, &high);
}
select(high+1, &fdrx, NULL, NULL, NULL);
for (i = 0; i < argc - 1; i++)
for (i = 0; i < trace_nr; i++) {
trace_handle(traces[i].trace, &fdrx);
}
if (doplot >= argc - 1) {
plot_values(traces, argc - 1);
if (doplot >= trace_nr) {
plot_values(traces, trace_nr);
doplot = 0;
samp_min = +INFINITY;
samp_max = -INFINITY;
}
} while (ret == 0);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment