chiark / gitweb /
Revert "bootchart: use _cleanup_close_"
[elogind.git] / src / bootchart / bootchart.c
index 0c4d3e3432eb29d6b9b9b164008086054cc19934..65f16c517c1b7cc9270dc48875101a9aa82cf899 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
  ***/
 
+/***
+
+  Many thanks to those who contributed ideas and code:
+  - Ziga Mahkovec - Original bootchart author
+  - Anders Norgaard - PyBootchartgui
+  - Michael Meeks - bootchart2
+  - Scott James Remnant - Ubuntu C-based logger
+  - Arjan van der Ven - for the idea to merge bootgraph.pl functionality
+
+ ***/
+
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/resource.h>
@@ -65,9 +76,10 @@ bool entropy = false;
 bool initcall = true;
 bool relative = false;
 bool filter = true;
+bool show_cmdline = false;
 bool pss = false;
 int samples;
-int len = 500; /* we record len+1 (1 start sample) */
+int samples_len = 500; /* we record len+1 (1 start sample) */
 double hz = 25.0;   /* 20 seconds log time */
 double scale_x = 100.0; /* 100px = 1sec */
 double scale_y = 20.0;  /* 16px = 1 process bar */
@@ -100,16 +112,16 @@ int main(int argc, char *argv[])
         char *init = NULL, *output = NULL;
 
         const ConfigTableItem items[] = {
-                { "Bootchart", "Samples",          config_parse_int,    0, &len      },
-                { "Bootchart", "Frequency",        config_parse_double, 0, &hz       },
-                { "Bootchart", "Relative",         config_parse_bool,   0, &relative },
-                { "Bootchart", "Filter",           config_parse_bool,   0, &filter   },
-                { "Bootchart", "Output",           config_parse_path,   0, &output   },
-                { "Bootchart", "Init",             config_parse_path,   0, &init     },
-                { "Bootchart", "PlotMemoryUsage",  config_parse_bool,   0, &pss      },
-                { "Bootchart", "PlotEntropyGraph", config_parse_bool,   0, &entropy  },
-                { "Bootchart", "ScaleX",           config_parse_double, 0, &scale_x  },
-                { "Bootchart", "ScaleY",           config_parse_double, 0, &scale_y  },
+                { "Bootchart", "Samples",          config_parse_int,    0, &samples_len },
+                { "Bootchart", "Frequency",        config_parse_double, 0, &hz          },
+                { "Bootchart", "Relative",         config_parse_bool,   0, &relative    },
+                { "Bootchart", "Filter",           config_parse_bool,   0, &filter      },
+                { "Bootchart", "Output",           config_parse_path,   0, &output      },
+                { "Bootchart", "Init",             config_parse_path,   0, &init        },
+                { "Bootchart", "PlotMemoryUsage",  config_parse_bool,   0, &pss         },
+                { "Bootchart", "PlotEntropyGraph", config_parse_bool,   0, &entropy     },
+                { "Bootchart", "ScaleX",           config_parse_double, 0, &scale_x     },
+                { "Bootchart", "ScaleY",           config_parse_double, 0, &scale_y     },
                 { NULL, NULL, NULL, 0, NULL }
         };
 
@@ -132,23 +144,24 @@ int main(int argc, char *argv[])
 
         while (1) {
                 static struct option opts[] = {
-                        {"rel",      no_argument,        NULL,  'r'},
-                        {"freq",     required_argument,  NULL,  'f'},
-                        {"samples",  required_argument,  NULL,  'n'},
-                        {"pss",      no_argument,        NULL,  'p'},
-                        {"output",   required_argument,  NULL,  'o'},
-                        {"init",     required_argument,  NULL,  'i'},
-                        {"filter",   no_argument,        NULL,  'F'},
-                        {"help",     no_argument,        NULL,  'h'},
-                        {"scale-x",  required_argument,  NULL,  'x'},
-                        {"scale-y",  required_argument,  NULL,  'y'},
-                        {"entropy",  no_argument,        NULL,  'e'},
+                        {"rel",       no_argument,        NULL,  'r'},
+                        {"freq",      required_argument,  NULL,  'f'},
+                        {"samples",   required_argument,  NULL,  'n'},
+                        {"pss",       no_argument,        NULL,  'p'},
+                        {"output",    required_argument,  NULL,  'o'},
+                        {"init",      required_argument,  NULL,  'i'},
+                        {"no-filter", no_argument,        NULL,  'F'},
+                        {"cmdline",   no_argument,        NULL,  'C'},
+                        {"help",      no_argument,        NULL,  'h'},
+                        {"scale-x",   required_argument,  NULL,  'x'},
+                        {"scale-y",   required_argument,  NULL,  'y'},
+                        {"entropy",   no_argument,        NULL,  'e'},
                         {NULL, 0, NULL, 0}
                 };
 
                 gind = 0;
 
-                i = getopt_long(argc, argv, "erpf:n:o:i:Fhx:y:", opts, &gind);
+                i = getopt_long(argc, argv, "erpf:n:o:i:FChx:y:", opts, &gind);
                 if (i == -1)
                         break;
                 switch (i) {
@@ -156,13 +169,22 @@ int main(int argc, char *argv[])
                         relative = true;
                         break;
                 case 'f':
-                        safe_atod(optarg, &hz);
+                        r = safe_atod(optarg, &hz);
+                        if (r < 0)
+                                log_warning("failed to parse --freq/-f argument '%s': %s",
+                                            optarg, strerror(-r));
                         break;
                 case 'F':
                         filter = false;
                         break;
+                case 'C':
+                        show_cmdline = true;
+                        break;
                 case 'n':
-                        safe_atoi(optarg, &len);
+                        r = safe_atoi(optarg, &samples_len);
+                        if (r < 0)
+                                log_warning("failed to parse --samples/-n argument '%s': %s",
+                                            optarg, strerror(-r));
                         break;
                 case 'o':
                         path_kill_slashes(optarg);
@@ -176,29 +198,37 @@ int main(int argc, char *argv[])
                         pss = true;
                         break;
                 case 'x':
-                        safe_atod(optarg, &scale_x);
+                        r = safe_atod(optarg, &scale_x);
+                        if (r < 0)
+                                log_warning("failed to parse --scale-x/-x argument '%s': %s",
+                                            optarg, strerror(-r));
                         break;
                 case 'y':
-                        safe_atod(optarg, &scale_y);
+                        r = safe_atod(optarg, &scale_y);
+                        if (r < 0)
+                                log_warning("failed to parse --scale-y/-y argument '%s': %s",
+                                            optarg, strerror(-r));
                         break;
                 case 'e':
                         entropy = true;
                         break;
                 case 'h':
                         fprintf(stderr, "Usage: %s [OPTIONS]\n", argv[0]);
-                        fprintf(stderr, " --rel,     -r            Record time relative to recording\n");
-                        fprintf(stderr, " --freq,    -f N          Sample frequency [%f]\n", hz);
-                        fprintf(stderr, " --samples, -n N          Stop sampling at [%d] samples\n", len);
-                        fprintf(stderr, " --scale-x, -x N          Scale the graph horizontally [%f] \n", scale_x);
-                        fprintf(stderr, " --scale-y, -y N          Scale the graph vertically [%f] \n", scale_y);
-                        fprintf(stderr, " --pss,     -p            Enable PSS graph (CPU intensive)\n");
-                        fprintf(stderr, " --entropy, -e            Enable the entropy_avail graph\n");
-                        fprintf(stderr, " --output,  -o [PATH]     Path to output files [%s]\n", output_path);
-                        fprintf(stderr, " --init,    -i [PATH]     Path to init executable [%s]\n", init_path);
-                        fprintf(stderr, " --filter,  -F            Disable filtering of processes from the graph\n");
+                        fprintf(stderr, " --rel,       -r          Record time relative to recording\n");
+                        fprintf(stderr, " --freq,      -f f        Sample frequency [%f]\n", hz);
+                        fprintf(stderr, " --samples,   -n N        Stop sampling at [%d] samples\n", samples_len);
+                        fprintf(stderr, " --scale-x,   -x N        Scale the graph horizontally [%f] \n", scale_x);
+                        fprintf(stderr, " --scale-y,   -y N        Scale the graph vertically [%f] \n", scale_y);
+                        fprintf(stderr, " --pss,       -p          Enable PSS graph (CPU intensive)\n");
+                        fprintf(stderr, " --entropy,   -e          Enable the entropy_avail graph\n");
+                        fprintf(stderr, " --output,    -o [PATH]   Path to output files [%s]\n", output_path);
+                        fprintf(stderr, " --init,      -i [PATH]   Path to init executable [%s]\n", init_path);
+                        fprintf(stderr, " --no-filter, -F          Disable filtering of processes from the graph\n");
                         fprintf(stderr, "                          that are of less importance or short-lived\n");
-                        fprintf(stderr, " --help,    -h            Display this message\n");
-                        fprintf(stderr, "See the installed README and bootchartd.conf.example for more information.\n");
+                        fprintf(stderr, " --cmdline,   -C          Display the full command line with arguments\n");
+                        fprintf(stderr, "                          of processes, instead of only the process name\n");
+                        fprintf(stderr, " --help,      -h          Display this message\n");
+                        fprintf(stderr, "See bootchart.conf for more information.\n");
                         exit (EXIT_SUCCESS);
                         break;
                 default:
@@ -206,7 +236,7 @@ int main(int argc, char *argv[])
                 }
         }
 
-        if (len > MAXSAMPLES) {
+        if (samples_len > MAXSAMPLES) {
                 fprintf(stderr, "Error: samples exceeds maximum\n");
                 exit(EXIT_FAILURE);
         }
@@ -217,7 +247,7 @@ int main(int argc, char *argv[])
         }
 
         /*
-         * If the kernel executed us through init=/sbin/bootchartd, then
+         * If the kernel executed us through init=/usr/lib/systemd/systemd-bootchart, then
          * fork:
          * - parent execs executable specified via init_path[] (/sbin/init by default) as pid=1
          * - child logs data
@@ -311,12 +341,12 @@ int main(int argc, char *argv[])
                 } else {
                         overrun++;
                         /* calculate how many samples we lost and scrap them */
-                        len = len + ((int)(newint_ns / interval));
+                        samples_len = samples_len + ((int)(newint_ns / interval));
                 }
 
                 samples++;
 
-                if (samples > len)
+                if (samples > samples_len)
                         break;
 
         }
@@ -341,13 +371,13 @@ int main(int argc, char *argv[])
         }
 
         if (!of) {
-                perror("open output_file");
+                fprintf(stderr, "opening output file '%s': %m\n", output_file);
                 exit (EXIT_FAILURE);
         }
 
         svg_do(build);
 
-        fprintf(stderr, "bootchartd: Wrote %s\n", output_file);
+        fprintf(stderr, "systemd-bootchart wrote %s\n", output_file);
         fclose(of);
 
         closedir(proc);
@@ -366,7 +396,7 @@ int main(int argc, char *argv[])
 
         /* don't complain when overrun once, happens most commonly on 1st sample */
         if (overrun > 1)
-                fprintf(stderr, "bootchartd: Warning: sample time overrun %i times\n", overrun);
+                fprintf(stderr, "systemd-boochart: Warning: sample time overrun %i times\n", overrun);
 
         return 0;
 }