systemctl: show timestamps for state changes

This commit is contained in:
Lennart Poettering 2010-08-25 03:13:44 +02:00
parent f1e36d677a
commit 584be568b9
3 changed files with 96 additions and 2 deletions

View File

@ -1489,6 +1489,11 @@ typedef struct UnitStatusInfo {
const char *path;
const char *default_control_group;
usec_t inactive_exit_timestamp;
usec_t active_enter_timestamp;
usec_t active_exit_timestamp;
usec_t inactive_enter_timestamp;
bool need_daemon_reload;
/* Service */
@ -1523,6 +1528,9 @@ typedef struct UnitStatusInfo {
static void print_status_info(UnitStatusInfo *i) {
ExecStatusInfo *p;
const char *on, *off, *ss;
usec_t timestamp;
char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
char since2[FORMAT_TIMESTAMP_MAX], *s2;
assert(i);
@ -1559,17 +1567,34 @@ static void print_status_info(UnitStatusInfo *i) {
on = off = "";
if (ss)
printf("\t Active: %s%s (%s)%s\n",
printf("\t Active: %s%s (%s)%s",
on,
strna(i->active_state),
ss,
off);
else
printf("\t Active: %s%s%s\n",
printf("\t Active: %s%s%s",
on,
strna(i->active_state),
off);
timestamp = (streq_ptr(i->active_state, "active") ||
streq_ptr(i->active_state, "reloading")) ? i->active_enter_timestamp :
(streq_ptr(i->active_state, "inactive") ||
streq_ptr(i->active_state, "maintenance")) ? i->inactive_enter_timestamp :
streq_ptr(i->active_state, "activating") ? i->inactive_exit_timestamp :
i->active_exit_timestamp;
s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
s2 = format_timestamp(since2, sizeof(since2), timestamp);
if (s1)
printf(" since [%s; %s]\n", s2, s1);
else if (s2)
printf(" since [%s]\n", s2);
else
printf("\n");
if (i->sysfs_path)
printf("\t Device: %s\n", i->sysfs_path);
else if (i->where)
@ -1782,6 +1807,14 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn
i->start_timestamp = (usec_t) u;
else if (streq(name, "ExecMainExitTimestamp"))
i->exit_timestamp = (usec_t) u;
else if (streq(name, "ActiveEnterTimestamp"))
i->active_enter_timestamp = (usec_t) u;
else if (streq(name, "InactiveEnterTimestamp"))
i->inactive_enter_timestamp = (usec_t) u;
else if (streq(name, "InactiveExitTimestamp"))
i->inactive_exit_timestamp = (usec_t) u;
else if (streq(name, "ActiveExitTimestamp"))
i->active_exit_timestamp = (usec_t) u;
break;
}

View File

@ -1659,6 +1659,63 @@ char *format_timestamp(char *buf, size_t l, usec_t t) {
return buf;
}
char *format_timestamp_pretty(char *buf, size_t l, usec_t t) {
usec_t n, d;
n = now(CLOCK_REALTIME);
if (t <= 0 || t > n || t + USEC_PER_DAY*7 <= t)
return NULL;
d = n - t;
if (d >= USEC_PER_YEAR)
snprintf(buf, l, "%llu years and %llu months ago",
(unsigned long long) (d / USEC_PER_YEAR),
(unsigned long long) ((d % USEC_PER_YEAR) / USEC_PER_MONTH));
else if (d >= USEC_PER_MONTH)
snprintf(buf, l, "%llu months and %llu days ago",
(unsigned long long) (d / USEC_PER_MONTH),
(unsigned long long) ((d % USEC_PER_MONTH) / USEC_PER_DAY));
else if (d >= USEC_PER_WEEK)
snprintf(buf, l, "%llu weeks and %llu days ago",
(unsigned long long) (d / USEC_PER_WEEK),
(unsigned long long) ((d % USEC_PER_WEEK) / USEC_PER_DAY));
else if (d >= 2*USEC_PER_DAY)
snprintf(buf, l, "%llu days ago", (unsigned long long) (d / USEC_PER_DAY));
else if (d >= 25*USEC_PER_HOUR)
snprintf(buf, l, "1 day and %lluh ago",
(unsigned long long) ((d - USEC_PER_DAY) / USEC_PER_HOUR));
else if (d >= 6*USEC_PER_HOUR)
snprintf(buf, l, "%lluh ago",
(unsigned long long) (d / USEC_PER_HOUR));
else if (d >= USEC_PER_HOUR)
snprintf(buf, l, "%lluh %llumin ago",
(unsigned long long) (d / USEC_PER_HOUR),
(unsigned long long) ((d % USEC_PER_HOUR) / USEC_PER_MINUTE));
else if (d >= 5*USEC_PER_MINUTE)
snprintf(buf, l, "%llumin ago",
(unsigned long long) (d / USEC_PER_MINUTE));
else if (d >= USEC_PER_MINUTE)
snprintf(buf, l, "%llumin %llus ago",
(unsigned long long) (d / USEC_PER_MINUTE),
(unsigned long long) ((d % USEC_PER_MINUTE) / USEC_PER_SEC));
else if (d >= USEC_PER_SEC)
snprintf(buf, l, "%llus ago",
(unsigned long long) (d / USEC_PER_SEC));
else if (d >= USEC_PER_MSEC)
snprintf(buf, l, "%llums ago",
(unsigned long long) (d / USEC_PER_MSEC));
else if (d > 0)
snprintf(buf, l, "%lluus ago",
(unsigned long long) d);
else
snprintf(buf, l, "now");
buf[l-1] = 0;
return buf;
}
char *format_timespan(char *buf, size_t l, usec_t t) {
static const struct {
const char *suffix;

View File

@ -52,12 +52,15 @@ typedef struct dual_timestamp {
#define USEC_PER_HOUR (60ULL*USEC_PER_MINUTE)
#define USEC_PER_DAY (24ULL*USEC_PER_HOUR)
#define USEC_PER_WEEK (7ULL*USEC_PER_DAY)
#define USEC_PER_MONTH (2629800ULL*USEC_PER_SEC)
#define USEC_PER_YEAR (31557600ULL*USEC_PER_SEC)
/* What is interpreted as whitespace? */
#define WHITESPACE " \t\n\r"
#define NEWLINE "\n\r"
#define FORMAT_TIMESTAMP_MAX 64
#define FORMAT_TIMESTAMP_PRETTY_MAX 256
#define FORMAT_TIMESPAN_MAX 64
#define ANSI_HIGHLIGHT_ON "\x1B[1;31m"
@ -248,6 +251,7 @@ bool ignore_file(const char *filename);
bool chars_intersect(const char *a, const char *b);
char *format_timestamp(char *buf, size_t l, usec_t t);
char *format_timestamp_pretty(char *buf, size_t l, usec_t t);
char *format_timespan(char *buf, size_t l, usec_t t);
int make_stdio(int fd);