diff --git a/src/process.h b/src/process.h index 15403fd..33fd6bf 100644 --- a/src/process.h +++ b/src/process.h @@ -28,12 +28,12 @@ typedef struct st_process { uint64_t swap; uint64_t written; uint64_t read; - - uint64_t childCpuTime; - uint64_t childMemory; - uint64_t childSwap; - uint64_t childRead; - uint64_t childWrite; + // cumulative fields - process + children + uint64_t cCpuTime; + uint64_t cMemory; + uint64_t cSwap; + uint64_t cRead; + uint64_t cWrite; } Process; #endif diff --git a/src/server.c b/src/server.c index 305a803..f2040df 100644 --- a/src/server.c +++ b/src/server.c @@ -59,6 +59,7 @@ int parseStatFile(Process *proc, char *filedata) { // (15) stime - %lu proc->cpuTime += fast_str2ull(&location); + proc->cCpuTime = proc->cpuTime; location += 1; // skip 16-19 @@ -81,12 +82,16 @@ int parseStatusFile(Process *proc, char *filedata) { proc->resident = 1024 * findAndParseField(&filedata, "VmRSS"); proc->swap = 1024 * findAndParseField(&filedata, "VmSwap"); + proc->cMemory = proc->resident; + proc->cSwap = proc->swap; return 0; } int parseIOFile(Process *proc, char *filedata) { proc->read = findAndParseField(&filedata, "read_bytes"); proc->written = findAndParseField(&filedata, "write_bytes"); + proc->cRead = proc->read; + proc->cWrite = proc->written; return 0; } @@ -172,7 +177,60 @@ nextProcess: } void aggregateStats(Process *head) { + int processCount = resetVisits(head); + Process *current = head; + int depth = 0; + int maxdepth = 0; + int visited = 0; + // assign depth (aka level) of each process + while (visited < processCount) { + if (current == NULL) { + printf("Bad visit count: %d visited of %d processes\n", visited, processCount); + break; + } + + current->visited = 1; + current->level = depth; + visited++; + + if (depth > maxdepth) maxdepth = depth; + +nextProcess: + if (current->child != NULL && !current->child->visited) { + // process children first + depth++; + current = current->child; + } else if (current->sibling != NULL) { + // process siblings next + current = current->sibling; + } else if (current->parent != NULL) { + // return to parent when tree is exhausted + depth--; + current = current->parent; + goto nextProcess; // parent was already visited, so find next process from parent + } else { + // no parent - scan for unvisited process + while (current != NULL && current->visited == 1) current = current->next; + } + } + + // scan for each depth level, tally stats upwards + for (depth=maxdepth; depth>0; depth--) { + current = head; + while (current != NULL) { + while (current != NULL && current->level != depth) current = current->next; + if (current == NULL) continue; + + Process *parent = current->parent; + parent->cCpuTime += current->cCpuTime; + parent->cMemory += current->cCpuTime; + parent->cSwap += current->cSwap; + parent->cRead += current->cRead; + parent->cWrite += current->cWrite; + current = current->next; + } + } } char *readProcesses(char *procdir) { @@ -256,10 +314,10 @@ char *readProcesses(char *procdir) { cur = cur->prev; free(cur->next); cur->next = NULL; - - printFamilyTree(head); + linkFamily(head); - printFamilyTree(head); + aggregateStats(head); + // printFamilyTree(head); int clocks = sysconf(_SC_CLK_TCK); char *output = malloc(8 * 1024 * 1024); @@ -272,14 +330,18 @@ char *readProcesses(char *procdir) { "pid=\"%d\",ppid=\"%d\",label=\"%s\",lxc=\"%d\"", cur->pid, cur->ppid, cur->label, cur->lxc); ptr += sprintf(ptr, "process_cpu_time_seconds{%s} %f\n", buffer, (double) cur->cpuTime / clocks); - ptr += sprintf(ptr, "process_child_cpu_time_seconds{%s} %f\n", buffer,(double) cur->childCpuTime / clocks); - ptr += sprintf(ptr, "process_num_threads{%s} %llu\n", buffer, cur->nThreads); - ptr += sprintf(ptr, "process_resident_bytes{%s} %llu\n", buffer, cur->resident); - ptr += sprintf(ptr, "process_swap_bytes{%s} %llu\n", buffer, cur->swap); - ptr += sprintf(ptr, "process_fileio_bytes_written{%s} %llu\n", buffer, cur->written); - ptr += sprintf(ptr, "process_fileio_bytes_read{%s} %llu\n", buffer, cur->read); + ptr += sprintf(ptr, "process_num_threads{%s} %lu\n", buffer, cur->nThreads); + ptr += sprintf(ptr, "process_resident_bytes{%s} %lu\n", buffer, cur->resident); + ptr += sprintf(ptr, "process_swap_bytes{%s} %lu\n", buffer, cur->swap); + ptr += sprintf(ptr, "process_fileio_bytes_written{%s} %lu\n", buffer, cur->written); + ptr += sprintf(ptr, "process_fileio_bytes_read{%s} %lu\n", buffer, cur->read); ptr += sprintf(ptr, "process_is_kernel_process{%s} %d\n", buffer, cur->iskernel); ptr += sprintf(ptr, "process_tree_depth{%s} %d\n", buffer, cur->level); + ptr += sprintf(ptr, "process_cumulative_cpu_time_seconds{%s} %lu\n", buffer, cur->cCpuTime); + ptr += sprintf(ptr, "process_cumulative_resident_bytes{%s} %lu\n", buffer, cur->cMemory); + ptr += sprintf(ptr, "process_cumulative_swap_bytes{%s} %lu\n", buffer, cur->cSwap); + ptr += sprintf(ptr, "process_cumulative_bytes_read{%s} %lu\n", buffer, cur->cRead); + ptr += sprintf(ptr, "process_cumulative_bytes_written{%s} %lu\n", buffer, cur->cWrite); // free and proceed Process *prev = cur; cur = cur->next; @@ -361,7 +423,7 @@ int main(int argc, char *argv[]) { if (argc == 1) { char *buf = readProcesses("/proc"); if (buf == NULL) return 4; - //printf(buf); + printf(buf); free(buf); return 0;