systemd-analyze.c revision c170f3a41bc69ad1eab2dba40cede865f2532bbc
5a1569832754da5d278b5ebf4f440e759df348a2Christian Maeder/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
5a1569832754da5d278b5ebf4f440e759df348a2Christian Maeder This file is part of systemd.
5a1569832754da5d278b5ebf4f440e759df348a2Christian Maeder Copyright 2010 Lennart Poettering
004b63663b1c5be6e6feddd43a7ca5d20121fa49Sebastian Raible systemd is free software; you can redistribute it and/or modify it
5a1569832754da5d278b5ebf4f440e759df348a2Christian Maeder under the terms of the GNU Lesser General Public License as published by
004b63663b1c5be6e6feddd43a7ca5d20121fa49Sebastian Raible the Free Software Foundation; either version 2.1 of the License, or
along with systemd; If not, see <http://www.gnu.org/licenses/>.
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <locale.h>
#include "install.h"
#include "log.h"
#include "dbus-common.h"
#include "build.h"
#include "util.h"
#include "strxcpyx.h"
#include "fileio.h"
(class), \
svg(" <text class=\"%s\" x=\"%.03f\" y=\"%.03f\">", (b) ? "left" : "right", scale_x * (x) + (b ? 5.0 : -5.0), scale_y * (y) + 14.0); \
static enum dot {
struct boot_times {
struct unit_times {
char *name;
static int bus_get_uint64_property(DBusConnection *bus, const char *path, const char *interface, const char *property, uint64_t *val) {
bus,
"org.freedesktop.systemd1",
path,
&reply,
NULL,
return -EIO;
return -EIO;
static int compare_unit_time(const void *a, const void *b) {
static int compare_unit_start(const void *a, const void *b) {
char *n = NULL;
return -ENOENT;
*_n = n;
struct unit_times *p;
free(t);
int r, c = 0, n_units = 0;
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
&reply,
NULL,
goto fail;
r = -EIO;
goto fail;
struct unit_info u;
struct unit_times *t;
r = -EIO;
goto fail;
if (c >= n_units) {
struct unit_times *w;
r = log_oom();
goto fail;
unit_times = w;
t = unit_times+c;
goto fail;
"org.freedesktop.systemd1.Unit",
&t->ixt) < 0 ||
"org.freedesktop.systemd1.Unit",
&t->aet) < 0 ||
"org.freedesktop.systemd1.Unit",
&t->axt) < 0 ||
"org.freedesktop.systemd1.Unit",
&t->iet) < 0) {
r = -EIO;
goto fail;
t->time = 0;
if (t->ixt == 0)
r = log_oom();
goto fail;
fail:
static bool cached = false;
if (cached)
goto finish;
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
return -EIO;
return -EAGAIN;
cached = true;
struct boot_times *t;
char *ptr;
if (t->firmware_time)
size = strpcpyf(&ptr, size, "%s (firmware) + ", format_timespan(ts, sizeof(ts), t->firmware_time - t->loader_time));
if (t->loader_time)
if (t->kernel_time)
size = strpcpyf(&ptr, size, "%s (kernel) + ", format_timespan(ts, sizeof(ts), t->kernel_done_time));
if (t->initrd_time > 0)
size = strpcpyf(&ptr, size, "%s (initrd) + ", format_timespan(ts, sizeof(ts), t->userspace_time - t->initrd_time));
size = strpcpyf(&ptr, size, "%s (userspace) ", format_timespan(ts, sizeof(ts), t->finish_time - t->userspace_time));
if (t->kernel_time > 0)
size = strpcpyf(&ptr, size, "= %s", format_timespan(ts, sizeof(ts), t->firmware_time + t->finish_time));
size = strpcpyf(&ptr, size, "= %s", format_timespan(ts, sizeof(ts), t->finish_time - t->userspace_time));
if (!ptr)
return log_oom();
double width;
struct unit_times *u;
double len;
"xmlns=\"http://www.w3.org/2000/svg\">\n\n",
"// line.sec1 { }\n"
" line.sec5 { stroke-width: 2; }\n"
" line.sec01 { stroke: rgb(224,224,224); stroke-width: 1; }\n"
" text.sec { font-size: 8; }\n"
svg("<text x=\"20\" y=\"%.0f\">Legend: Red = Activating; Pink = Active; Dark Pink = Deactivating</text>",
if (!u->name)
svg_text(false, u->ixt, y, u->time? "%s (%s)" : "%s", u->name, format_timespan(ts, sizeof(ts), u->time));
svg_text(true, u->ixt, y, u->time? "%s (%s)" : "%s", u->name, format_timespan(ts, sizeof(ts), u->time));
static const char * const colors[] = {
const char *c = NULL;
assert(u);
bus,
"org.freedesktop.systemd1",
u->unit_path,
&reply,
NULL,
return -EIO;
const char *prop;
return -EIO;
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
&reply,
NULL,
return -EIO;
struct unit_info u;
return -EIO;
if (on_tty())
"-- Try a shell pipeline like 'systemd-analyze dot | dot -Tsvg > systemd.svg'!\n");
static void analyze_help(void)
analyze_help();
case ARG_VERSION:
case ARG_USER:
case ARG_SYSTEM:
case ARG_ORDER:
case ARG_REQUIRE:
return -EINVAL;
log_open();
return EXIT_FAILURE;
return EXIT_SUCCESS;
if (!bus)
return EXIT_FAILURE;