1 /* 2 * Copyright 2014 The Chromium Authors. All rights reserved. 3 * Use of this source code is governed by a BSD-style license that can be 4 * found in the LICENSE file. 5 */ 6 7 #include <ctype.h> 8 #include <dirent.h> 9 #include <stdbool.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <time.h> 14 #include <unistd.h> 15 16 /* 17 * This tool is essentially an extended version of ps with JSON output. 18 * Its output is meant consumed by scripts / tools for gathering OS/ps stats. 19 * Output units: 20 * All times are expressed in ticks. 21 * All memory counters are expressed in Kb. 22 */ 23 24 static void dump_time(void) { 25 float uptime_secs = 0.0F; 26 const long rate = sysconf(_SC_CLK_TCK); 27 FILE *f = fopen("/proc/uptime", "r"); 28 if (!f) 29 return; 30 fscanf(f, "%f", &uptime_secs); 31 fclose(f); 32 const long ticks = (long) (rate * uptime_secs); 33 printf(" \"time\": { \"ticks\": %ld, \"rate\": %ld}", ticks, rate); 34 } 35 36 static void dump_cpu_stats(void) { 37 FILE *f = fopen("/proc/stat", "r"); 38 if (!f) 39 return; 40 printf(" \"cpu\":\n [\n"); 41 42 bool terminate_prev_line = false; 43 while (!feof(f)) { 44 char line[256]; 45 char cpu[8]; 46 long unsigned t_usr = 0; 47 long unsigned t_nice = 0; 48 long unsigned t_sys = 0; 49 long unsigned t_idle = 0; 50 fgets(line, sizeof(line), f); 51 52 /* Skip the total 'cpu ' line and the other irrelevant ones. */ 53 if (strncmp(line, "cpu", 3) != 0 || line[3] == ' ') 54 continue; 55 if (sscanf(line, "%s %lu %lu %lu %lu", 56 cpu, &t_usr, &t_nice, &t_sys, &t_idle) != 5) { 57 continue; 58 } 59 60 if (terminate_prev_line) 61 printf(",\n"); 62 terminate_prev_line = true; 63 printf(" {\"usr\": %lu, \"sys\": %lu, \"idle\": %lu}", 64 t_usr + t_nice, t_sys, t_idle); 65 } 66 fclose(f); 67 printf("\n ]"); 68 } 69 70 static void dump_mem_stats(void) { 71 FILE *f = fopen("/proc/meminfo", "r"); 72 if (!f) 73 return; 74 printf(" \"mem\":\n {\n"); 75 76 bool terminate_prev_line = false; 77 while (!feof(f)) { 78 char line[256]; 79 char key[32]; 80 long value = 0; 81 82 fgets(line, sizeof(line), f); 83 if (sscanf(line, "%s %lu %*s", key, &value) < 2) 84 continue; 85 86 if (terminate_prev_line) 87 printf(",\n"); 88 terminate_prev_line = true; 89 printf(" \"%s\": %lu", key, value); 90 } 91 fclose(f); 92 printf("\n }"); 93 } 94 95 static void dump_proc_stats(void) { 96 struct dirent *de; 97 DIR *d = opendir("/proc"); 98 if (!d) 99 return; 100 101 const long kb_per_page = sysconf(_SC_PAGESIZE) / 1024; 102 bool terminate_prev_line = false; 103 printf(" \"processes\":\n {\n"); 104 while ((de = readdir(d))) { 105 if (!isdigit(de->d_name[0])) 106 continue; 107 const int pid = atoi(de->d_name); 108 109 /* Don't print out ourselves (how civilized). */ 110 if (pid == getpid()) 111 continue; 112 113 char cmdline[64]; 114 char fpath[32]; 115 FILE *f; 116 117 /* Read full process path / package from cmdline. */ 118 sprintf(fpath, "/proc/%d/cmdline", pid); 119 f = fopen(fpath, "r"); 120 if (!f) 121 continue; 122 cmdline[0] = '\0'; 123 fgets(cmdline, sizeof(cmdline), f); 124 fclose(f); 125 126 /* Read cpu/io/mem stats. */ 127 char proc_name[256]; 128 long num_threads = 0; 129 long unsigned min_faults = 0; 130 long unsigned maj_faults = 0; 131 long unsigned utime = 0; 132 long unsigned ktime = 0; 133 long unsigned vm_rss = 0; 134 long long unsigned start_time = 0; 135 136 sprintf(fpath, "/proc/%d/stat", pid); 137 f = fopen(fpath, "r"); 138 if (!f) 139 continue; 140 fscanf(f, "%*d %s %*c %*d %*d %*d %*d %*d %*u %lu %*u %lu %*u %lu %lu " 141 "%*d %*d %*d %*d %ld %*d %llu %*u %ld", proc_name, &min_faults, 142 &maj_faults, &utime, &ktime, &num_threads, &start_time, &vm_rss); 143 fclose(f); 144 145 /* Prefer the cmdline when available, since it contains the package name. */ 146 char const * const cmd = (strlen(cmdline) > 0) ? cmdline : proc_name; 147 148 if (terminate_prev_line) 149 printf(",\n"); 150 terminate_prev_line = true; 151 printf(" \"%d\": {" 152 "\"name\": \"%s\", " 153 "\"n_threads\": %ld, " 154 "\"start_time\": %llu, " 155 "\"user_time\": %lu, " 156 "\"sys_time\": %lu, " 157 "\"min_faults\": %lu, " 158 "\"maj_faults\": %lu, " 159 "\"vm_rss\": %lu" 160 "}", 161 pid, 162 cmd, 163 num_threads, 164 start_time, 165 utime, 166 ktime, 167 min_faults, 168 maj_faults, 169 vm_rss * kb_per_page); 170 } 171 closedir(d); 172 printf("\n }"); 173 } 174 175 int main() 176 { 177 printf("{\n"); 178 179 dump_time(); 180 printf(",\n"); 181 182 dump_mem_stats(); 183 printf(",\n"); 184 185 dump_cpu_stats(); 186 printf(",\n"); 187 188 dump_proc_stats(); 189 printf("\n}\n"); 190 191 return 0; 192 } 193