Mercurial > dovecot > core-2.2
changeset 13457:835891cf2eef
stats: Track [rw]char and sysc[rw] fields in /proc/self/io (with Linux).
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 12 Sep 2011 18:29:17 +0300 |
parents | b1870cf2d3ff |
children | e60a3b29117c |
files | src/plugins/stats/stats-plugin.c src/plugins/stats/stats-plugin.h src/stats/client-export.c src/stats/mail-stats.c src/stats/mail-stats.h |
diffstat | 5 files changed, 92 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/src/plugins/stats/stats-plugin.c Mon Sep 12 18:26:29 2011 +0300 +++ b/src/plugins/stats/stats-plugin.c Mon Sep 12 18:29:17 2011 +0300 @@ -81,6 +81,70 @@ trans_stats_add(dest_r, &strans->trans->stats); } +static int +process_io_buffer_parse(const char *buf, struct mail_stats *stats) +{ + const char *const *tmp; + + tmp = t_strsplit(buf, "\n"); + for (; *tmp != NULL; tmp++) { + if (strncmp(*tmp, "rchar: ", 7) == 0) { + if (str_to_uint64(*tmp + 7, &stats->read_bytes) < 0) + return -1; + } else if (strncmp(*tmp, "wchar: ", 7) == 0) { + if (str_to_uint64(*tmp + 7, &stats->write_bytes) < 0) + return -1; + } else if (strncmp(*tmp, "syscr: ", 7) == 0) { + if (str_to_uint32(*tmp + 7, &stats->read_count) < 0) + return -1; + } else if (strncmp(*tmp, "syscw: ", 7) == 0) { + if (str_to_uint32(*tmp + 7, &stats->write_count) < 0) + return -1; + } + } + return 0; +} + +static void process_read_io_stats(struct mail_stats *stats) +{ + const char *path = "/proc/self/io"; + static bool io_disabled = FALSE; + char buf[1024]; + int fd, ret; + + if (io_disabled) + return; + + fd = open(path, O_RDONLY); + if (fd == -1) { + if (errno != ENOENT) + i_error("open(%s) failed: %m", path); + io_disabled = TRUE; + return; + } + ret = read(fd, buf, sizeof(buf)); + if (ret <= 0) { + if (ret == -1) + i_error("read(%s) failed: %m", path); + else + i_error("read(%s) returned EOF", path); + } else if (ret == sizeof(buf)) { + /* just shouldn't happen.. */ + i_error("%s is larger than expected", path); + io_disabled = TRUE; + } else { + buf[ret] = '\0'; + T_BEGIN { + if (process_io_buffer_parse(buf, stats) < 0) { + i_error("Invalid input in file %s", path); + io_disabled = TRUE; + } + } T_END; + } + if (close(fd) < 0) + i_error("close(%s) failed: %m", path); +} + void mail_stats_get(struct stats_user *suser, struct mail_stats *stats_r) { struct rusage usage; @@ -97,6 +161,7 @@ stats_r->invol_cs = usage.ru_nivcsw; stats_r->disk_input = (unsigned long long)usage.ru_inblock * 512ULL; stats_r->disk_output = (unsigned long long)usage.ru_oublock * 512ULL; + process_read_io_stats(stats_r); user_trans_stats_get(suser, &stats_r->trans_stats); } @@ -213,6 +278,10 @@ dest->maj_faults += new_stats->maj_faults - old_stats->maj_faults; dest->vol_cs += new_stats->vol_cs - old_stats->vol_cs; dest->invol_cs += new_stats->invol_cs - old_stats->invol_cs; + dest->read_count += new_stats->read_count - old_stats->read_count; + dest->write_count += new_stats->write_count - old_stats->write_count; + dest->read_bytes += new_stats->read_bytes - old_stats->read_bytes; + dest->write_bytes += new_stats->write_bytes - old_stats->write_bytes; timeval_add_diff(&dest->user_cpu, &new_stats->user_cpu, &old_stats->user_cpu); @@ -238,6 +307,12 @@ (unsigned long long)stats->disk_input); str_printfa(str, "\tdiskout=%llu", (unsigned long long)stats->disk_output); + str_printfa(str, "\trchar=%llu", + (unsigned long long)stats->read_bytes); + str_printfa(str, "\twchar=%llu", + (unsigned long long)stats->write_bytes); + str_printfa(str, "\tsyscr=%u", stats->read_count); + str_printfa(str, "\tsyscw=%u", stats->write_count); str_printfa(str, "\tmlpath=%lu", tstats->open_lookup_count + tstats->stat_lookup_count); str_printfa(str, "\tmlattr=%lu", @@ -278,6 +353,8 @@ return TRUE; if (cur->invol_cs > prev->invol_cs+10) return TRUE; + /* don't check for read/write count/bytes changes, since they get + changed by stats checking itself */ return FALSE; }
--- a/src/plugins/stats/stats-plugin.h Mon Sep 12 18:26:29 2011 +0300 +++ b/src/plugins/stats/stats-plugin.h Mon Sep 12 18:29:17 2011 +0300 @@ -18,6 +18,9 @@ uint32_t vol_cs, invol_cs; /* disk input/output bytes */ uint64_t disk_input, disk_output; + /* read()/write() syscall count and number of bytes */ + uint32_t read_count, write_count; + uint64_t read_bytes, write_bytes; struct mailbox_transaction_stats trans_stats; };
--- a/src/stats/client-export.c Mon Sep 12 18:26:29 2011 +0300 +++ b/src/stats/client-export.c Mon Sep 12 18:29:17 2011 +0300 @@ -100,6 +100,7 @@ #define MAIL_STATS_HEADER "\tuser_cpu\tsys_cpu" \ "\tmin_faults\tmaj_faults\tvol_cs\tinvol_cs" \ "\tdisk_input\tdisk_output" \ + "\tread_count\tread_bytes\twrite_count\twrite_bytes" \ "\tmail_lookup_path\tmail_lookup_attr" \ "\tmail_read_count\tmail_read_bytes\tmail_cache_hits\n" @@ -112,6 +113,9 @@ str_printfa(str, "\t%llu\t%llu", (unsigned long long)stats->disk_input, (unsigned long long)stats->disk_output); + str_printfa(str, "\t%u\t%llu\t%u\t%llu", + stats->read_count, (unsigned long long)stats->read_bytes, + stats->write_count, (unsigned long long)stats->write_bytes); str_printfa(str, "\t%u\t%u\t%u\t%llu\t%u", stats->mail_lookup_path, stats->mail_lookup_attr, stats->mail_read_count,
--- a/src/stats/mail-stats.c Mon Sep 12 18:26:29 2011 +0300 +++ b/src/stats/mail-stats.c Mon Sep 12 18:29:17 2011 +0300 @@ -26,6 +26,11 @@ EN("diskin", disk_input), EN("diskout", disk_output), + EN("rchar", read_bytes), + EN("wchar", write_bytes), + EN("syscr", read_count), + EN("syscw", write_count), + EN("mlpath", mail_lookup_path), EN("mlattr", mail_lookup_attr), EN("mrcount", mail_read_count),
--- a/src/stats/mail-stats.h Mon Sep 12 18:26:29 2011 +0300 +++ b/src/stats/mail-stats.h Mon Sep 12 18:29:17 2011 +0300 @@ -10,6 +10,9 @@ uint32_t vol_cs, invol_cs; uint64_t disk_input, disk_output; + uint32_t read_count, write_count; + uint64_t read_bytes, write_bytes; + uint32_t mail_lookup_path, mail_lookup_attr, mail_read_count; uint32_t mail_cache_hits; uint64_t mail_read_bytes;