ircd::fs::dev: Add stats gather struct w/ console cmd.
This commit is contained in:
parent
f85781b65a
commit
43838608fd
|
@ -14,6 +14,7 @@
|
|||
namespace ircd::fs::dev
|
||||
{
|
||||
struct blk;
|
||||
struct stats;
|
||||
|
||||
using major_minor = std::pair<ulong, ulong>;
|
||||
|
||||
|
@ -69,6 +70,44 @@ struct ircd::fs::dev::blk
|
|||
static bool for_each(const closure &);
|
||||
};
|
||||
|
||||
struct ircd::fs::dev::stats
|
||||
{
|
||||
using closure = util::function_bool<const stats &>;
|
||||
|
||||
char name[32] {0};
|
||||
major_minor id {0, 0};
|
||||
|
||||
uint64_t read {0};
|
||||
uint64_t read_merged {0};
|
||||
uint64_t read_sectors {0};
|
||||
milliseconds read_time {0ms};
|
||||
|
||||
uint64_t write {0};
|
||||
uint64_t write_merged {0};
|
||||
uint64_t write_sectors {0};
|
||||
milliseconds write_time {0ms};
|
||||
|
||||
uint64_t io_current {0};
|
||||
milliseconds io_time {0ms};
|
||||
milliseconds io_weighted_time {0ms};
|
||||
|
||||
// 4.18+
|
||||
uint64_t discard {0};
|
||||
uint64_t discard_merged {0};
|
||||
uint64_t discard_sectors {0};
|
||||
milliseconds discard_time {0ms};
|
||||
|
||||
// 5.5+
|
||||
uint64_t flush {0};
|
||||
milliseconds flush_time {0ms};
|
||||
|
||||
stats(const string_view &line);
|
||||
stats() = default;
|
||||
|
||||
static bool for_each(const closure &);
|
||||
static stats get(const major_minor &id);
|
||||
};
|
||||
|
||||
/// Return a lex_cast'able (an integer) from a sysfs target.
|
||||
template<class T,
|
||||
size_t bufmax>
|
||||
|
|
|
@ -231,3 +231,100 @@ ircd::fs::dev::blk::devtype(const mutable_buffer &buf,
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//
|
||||
// dev::stats
|
||||
//
|
||||
|
||||
ircd::fs::dev::stats
|
||||
ircd::fs::dev::stats::get(const major_minor &id)
|
||||
{
|
||||
stats ret;
|
||||
for_each([&id, &ret]
|
||||
(const auto &stats)
|
||||
{
|
||||
if(stats.id == id)
|
||||
{
|
||||
ret = stats;
|
||||
return false;
|
||||
}
|
||||
else return true;
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::fs::dev::stats::for_each(const closure &closure)
|
||||
{
|
||||
thread_local char buf[16_KiB];
|
||||
|
||||
const fs::fd fd
|
||||
{
|
||||
"/proc/diskstats", fs::fd::opts
|
||||
{
|
||||
.mode = std::ios::in,
|
||||
},
|
||||
};
|
||||
|
||||
fs::read_opts opts;
|
||||
opts.aio = false;
|
||||
const string_view read
|
||||
{
|
||||
fs::read(fd, buf, opts)
|
||||
};
|
||||
|
||||
return tokens(read, '\n', [&closure]
|
||||
(const auto &line)
|
||||
{
|
||||
return closure(stats(line));
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// dev::stats::stats
|
||||
//
|
||||
|
||||
ircd::fs::dev::stats::stats(const string_view &line)
|
||||
{
|
||||
string_view item[20];
|
||||
const auto items
|
||||
{
|
||||
tokens(line, ' ', item)
|
||||
};
|
||||
|
||||
id.first = lex_cast<uint64_t>(item[0]);
|
||||
id.second = lex_cast<uint64_t>(item[1]);
|
||||
strlcpy(name, item[2]);
|
||||
|
||||
read = lex_cast<uint64_t>(item[3]);
|
||||
read_merged = lex_cast<uint64_t>(item[4]);
|
||||
read_sectors = lex_cast<uint64_t>(item[5]);
|
||||
read_time = lex_cast<milliseconds>(item[6]);
|
||||
|
||||
write = lex_cast<uint64_t>(item[7]);
|
||||
write_merged = lex_cast<uint64_t>(item[8]);
|
||||
write_sectors = lex_cast<uint64_t>(item[9]);
|
||||
write_time = lex_cast<milliseconds>(item[10]);
|
||||
|
||||
io_current = lex_cast<uint64_t>(item[11]);
|
||||
io_time = lex_cast<milliseconds>(item[12]);
|
||||
io_weighted_time = lex_cast<milliseconds>(item[13]);
|
||||
|
||||
if(items <= 14)
|
||||
return;
|
||||
|
||||
discard = lex_cast<uint64_t>(item[14]);
|
||||
discard_merged = lex_cast<uint64_t>(item[15]);
|
||||
discard_sectors = lex_cast<uint64_t>(item[16]);
|
||||
discard_time = lex_cast<milliseconds>(item[17]);
|
||||
|
||||
if(items <= 18)
|
||||
return;
|
||||
|
||||
flush = lex_cast<uint64_t>(item[18]);
|
||||
flush_time = lex_cast<milliseconds>(item[19]);
|
||||
|
||||
if(items <= 20)
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1087,6 +1087,78 @@ console_cmd__fs__dev(opt &out, const string_view &line)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
console_cmd__fs__dev__stats(opt &out, const string_view &line)
|
||||
{
|
||||
const params param{line, " ",
|
||||
{
|
||||
"name"
|
||||
}};
|
||||
|
||||
const string_view name
|
||||
{
|
||||
param["name"]
|
||||
};
|
||||
|
||||
out
|
||||
<< std::setw(3) << std::right << "maj" << ':'
|
||||
<< std::setw(3) << std::left << "min" << ' '
|
||||
<< std::setw(18) << std::left << "name" << ' '
|
||||
<< std::setw(6) << std::right << "io cur" << ' '
|
||||
<< std::setw(12) << std::right << "io time" << ' '
|
||||
<< std::setw(12) << std::right << "io weighted" << ' '
|
||||
<< std::setw(12) << std::right << "reads" << ' '
|
||||
<< std::setw(12) << std::right << "read sect" << ' '
|
||||
<< std::setw(12) << std::right << "read merge" << ' '
|
||||
<< std::setw(12) << std::right << "read time" << ' '
|
||||
<< std::setw(12) << std::right << "writes" << ' '
|
||||
<< std::setw(12) << std::right << "write sect" << ' '
|
||||
<< std::setw(12) << std::right << "write merge" << ' '
|
||||
<< std::setw(12) << std::right << "write time" << ' '
|
||||
<< std::setw(12) << std::right << "discards" << ' '
|
||||
<< std::setw(12) << std::right << "discard sect" << ' '
|
||||
<< std::setw(12) << std::right << "discard merg" << ' '
|
||||
<< std::setw(12) << std::right << "discard time" << ' '
|
||||
<< std::setw(12) << std::right << "flushes" << ' '
|
||||
<< std::setw(12) << std::right << "flush time" << ' '
|
||||
<< std::endl;
|
||||
|
||||
fs::dev::stats::for_each([&out, &name]
|
||||
(const auto &stats)
|
||||
{
|
||||
if(name && !startswith(stats.name, name))
|
||||
return true;
|
||||
|
||||
char tmbuf[8][32];
|
||||
out
|
||||
<< std::setw(3) << std::right << stats.id.first << ':'
|
||||
<< std::setw(3) << std::left << stats.id.second << ' '
|
||||
<< std::setw(18) << std::left << stats.name << ' '
|
||||
<< std::setw(6) << std::right << stats.io_current << ' '
|
||||
<< std::setw(12) << std::right << pretty(tmbuf[0], stats.io_time, 1) << ' '
|
||||
<< std::setw(12) << std::right << pretty(tmbuf[1], stats.io_weighted_time, 1) << ' '
|
||||
<< std::setw(12) << std::right << stats.read << ' '
|
||||
<< std::setw(12) << std::right << stats.read_merged << ' '
|
||||
<< std::setw(12) << std::right << stats.read_sectors << ' '
|
||||
<< std::setw(12) << std::right << pretty(tmbuf[2], stats.read_time, 1) << ' '
|
||||
<< std::setw(12) << std::right << stats.write << ' '
|
||||
<< std::setw(12) << std::right << stats.write_merged << ' '
|
||||
<< std::setw(12) << std::right << stats.write_sectors << ' '
|
||||
<< std::setw(12) << std::right << pretty(tmbuf[3], stats.write_time, 1) << ' '
|
||||
<< std::setw(12) << std::right << stats.discard << ' '
|
||||
<< std::setw(12) << std::right << stats.discard_merged << ' '
|
||||
<< std::setw(12) << std::right << stats.discard_sectors << ' '
|
||||
<< std::setw(12) << std::right << pretty(tmbuf[4], stats.discard_time, 1) << ' '
|
||||
<< std::setw(12) << std::right << stats.flush << ' '
|
||||
<< std::setw(12) << std::right << pretty(tmbuf[5], stats.flush_time, 1) << ' '
|
||||
<< '\n';
|
||||
return !name;
|
||||
});
|
||||
|
||||
out << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
console_cmd__ls(opt &out, const string_view &line)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue