trace(1): add basic support for timestamps
This patch adds strace-like support for a -t command line option, which causes a timestamp to be printed at the beginning of each line. If the option is given more than once, the output will also include microseconds. Change-Id: I8cda581651859448c154b01815cc49d915b7b354
This commit is contained in:
parent
1bb466dd36
commit
10a44c0ee2
@ -165,15 +165,18 @@ output_flush(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Print a PID prefix for the given process, or an info prefix if no process
|
* Print a prefix for a line of output. Possibly print a timestamp first.
|
||||||
* (NULL) is given. Prefixes are only relevant when multiple processes are
|
* Then, if applicable, print a PID prefix for the given process, or an info
|
||||||
* traced. As long as there are multiple processes, each line is prefixed with
|
* prefix if no process (NULL) is given.
|
||||||
* the PID of the process. As soon as the number of processes has been reduced
|
*
|
||||||
* back to one, one more line is prefixed with the PID of the remaining process
|
* PIDs are relevant only when multiple processes are traced. As long as there
|
||||||
* (with a "'" instead of a "|") to help the user identify which process is
|
* are multiple processes, each line is prefixed with the PID of the process.
|
||||||
* left. In addition, whenever a preempted call is about to be resumed, a "*"
|
* As soon as the number of processes has been reduced back to one, one more
|
||||||
* is printed instead of a space, so as to show that it is a continuation of a
|
* line is prefixed with the PID of the remaining process (with a "'" instead
|
||||||
* previous line. An example of all these cases:
|
* of a "|") to help the user identify which process remains. In addition,
|
||||||
|
* whenever a preempted call is about to be resumed, a "*" is printed instead
|
||||||
|
* of a space, so as to show that it is a continuation of a previous line. An
|
||||||
|
* example of all these cases:
|
||||||
*
|
*
|
||||||
* fork() = 3
|
* fork() = 3
|
||||||
* 3| Tracing test (pid 3)
|
* 3| Tracing test (pid 3)
|
||||||
@ -191,11 +194,33 @@ output_flush(void)
|
|||||||
static void
|
static void
|
||||||
put_prefix(struct trace_proc * proc, int resuming)
|
put_prefix(struct trace_proc * proc, int resuming)
|
||||||
{
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
struct tm *tm;
|
||||||
char prefix[32];
|
char prefix[32];
|
||||||
unsigned int count;
|
unsigned int off, count;
|
||||||
|
|
||||||
assert(line_off == 0);
|
assert(line_off == 0);
|
||||||
|
|
||||||
|
off = 0;
|
||||||
|
|
||||||
|
if (timestamps > 0) {
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
|
||||||
|
tm = gmtime(&tv.tv_sec);
|
||||||
|
|
||||||
|
off = strftime(prefix, sizeof(prefix), "%T", tm);
|
||||||
|
|
||||||
|
if (timestamps > 1)
|
||||||
|
off += snprintf(&prefix[off], sizeof(prefix) - off,
|
||||||
|
".%06u", tv.tv_usec);
|
||||||
|
|
||||||
|
assert(off < sizeof(prefix) - 2);
|
||||||
|
prefix[off++] = ' ';
|
||||||
|
prefix[off] = '\0';
|
||||||
|
|
||||||
|
off = output_write(prefix);
|
||||||
|
}
|
||||||
|
|
||||||
count = proc_count();
|
count = proc_count();
|
||||||
|
|
||||||
/* TODO: add a command line option for always printing the pid. */
|
/* TODO: add a command line option for always printing the pid. */
|
||||||
@ -212,14 +237,14 @@ put_prefix(struct trace_proc * proc, int resuming)
|
|||||||
proc->pid, (count > 1) ? '|' : '\'',
|
proc->pid, (count > 1) ? '|' : '\'',
|
||||||
resuming ? '*' : ' ');
|
resuming ? '*' : ' ');
|
||||||
|
|
||||||
prefix_off = line_off = output_write(prefix);
|
off += output_write(prefix);
|
||||||
|
|
||||||
last_pid = (proc != NULL ? proc->pid : 0);
|
last_pid = (proc != NULL ? proc->pid : 0);
|
||||||
} else {
|
} else
|
||||||
assert(!resuming);
|
assert(!resuming);
|
||||||
|
|
||||||
prefix_off = 0;
|
prefix_off = off;
|
||||||
}
|
line_off += off;
|
||||||
|
|
||||||
/* Remember whether the next line should get prefixed regardless. */
|
/* Remember whether the next line should get prefixed regardless. */
|
||||||
print_pid = (count > 1 || proc == NULL);
|
print_pid = (count > 1 || proc == NULL);
|
||||||
|
@ -96,6 +96,7 @@ unsigned int proc_count(void);
|
|||||||
const char *get_signal_name(int sig);
|
const char *get_signal_name(int sig);
|
||||||
|
|
||||||
/* trace.c */
|
/* trace.c */
|
||||||
|
extern int timestamps;
|
||||||
extern int allnames;
|
extern int allnames;
|
||||||
extern unsigned int verbose;
|
extern unsigned int verbose;
|
||||||
extern unsigned int valuesonly;
|
extern unsigned int valuesonly;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
.Nd print process system calls and signals
|
.Nd print process system calls and signals
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm
|
.Nm
|
||||||
.Op Fl fgNsVv
|
.Op Fl fgNstVv
|
||||||
.Op Fl o Ar file
|
.Op Fl o Ar file
|
||||||
.Op Fl p Ar pid
|
.Op Fl p Ar pid
|
||||||
.Op Ar command
|
.Op Ar command
|
||||||
@ -58,6 +58,14 @@ preceded by a line showing the process's current stack trace.
|
|||||||
For signals blocked by the target process, the stack trace may not be
|
For signals blocked by the target process, the stack trace may not be
|
||||||
meaningful.
|
meaningful.
|
||||||
Stack traces may not be supported on all platforms.
|
Stack traces may not be supported on all platforms.
|
||||||
|
.It Fl t
|
||||||
|
Print timestamps.
|
||||||
|
By default, no timestamps are printed.
|
||||||
|
If this flag is given once, each line will be prefixed by the current time.
|
||||||
|
If this flag is given twice, the time will also include microseconds.
|
||||||
|
The printed timestamp corresponds to the time at which printing of the rest of
|
||||||
|
the line was initiated, which in the case of call resumption may not be the
|
||||||
|
same as the time that the system call was initiated.
|
||||||
.It Fl V
|
.It Fl V
|
||||||
Print values only.
|
Print values only.
|
||||||
If this flag is given once, numerical values will be printed instead of
|
If this flag is given once, numerical values will be printed instead of
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
|
||||||
/* Global variables, used only for a subset of the command line options. */
|
/* Global variables, used only for a subset of the command line options. */
|
||||||
|
int timestamps; /* 0 = none, 1 = time w/o usecs, 2 = time w/usecs */
|
||||||
int allnames; /* FALSE = structure field names, TRUE = all names */
|
int allnames; /* FALSE = structure field names, TRUE = all names */
|
||||||
unsigned int valuesonly; /* 0 = normal, 1 = no symbols, 2 = no structures */
|
unsigned int valuesonly; /* 0 = normal, 1 = no symbols, 2 = no structures */
|
||||||
unsigned int verbose; /* 0 = essentials, 1 = elaborate, 2 = everything */
|
unsigned int verbose; /* 0 = essentials, 1 = elaborate, 2 = everything */
|
||||||
@ -444,7 +445,7 @@ static void __dead
|
|||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
(void)fprintf(stderr, "usage: %s [-fgNsVv] [-o file] [-p pid] "
|
(void)fprintf(stderr, "usage: %s [-fgNstVv] [-o file] [-p pid] "
|
||||||
"[command]\n", getprogname());
|
"[command]\n", getprogname());
|
||||||
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -471,11 +472,12 @@ main(int argc, char * argv[])
|
|||||||
grouping = FALSE;
|
grouping = FALSE;
|
||||||
output_file = NULL;
|
output_file = NULL;
|
||||||
|
|
||||||
|
timestamps = 0;
|
||||||
allnames = FALSE;
|
allnames = FALSE;
|
||||||
verbose = 0;
|
verbose = 0;
|
||||||
valuesonly = 0;
|
valuesonly = 0;
|
||||||
|
|
||||||
while ((c = getopt(argc, argv, "fgNsVvo:p:")) != -1) {
|
while ((c = getopt(argc, argv, "fgNstVvo:p:")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'f':
|
case 'f':
|
||||||
follow_fork = TRUE;
|
follow_fork = TRUE;
|
||||||
@ -489,6 +491,9 @@ main(int argc, char * argv[])
|
|||||||
case 's':
|
case 's':
|
||||||
show_stack = TRUE;
|
show_stack = TRUE;
|
||||||
break;
|
break;
|
||||||
|
case 't':
|
||||||
|
timestamps++;
|
||||||
|
break;
|
||||||
case 'V':
|
case 'V':
|
||||||
valuesonly++;
|
valuesonly++;
|
||||||
break;
|
break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user