// ----------------------------------------------------------------------
// File: Stat.cc
// Author: Andreas-Joachim Peters - CERN
// ----------------------------------------------------------------------
/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2016 CERN/Switzerland *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see .*
************************************************************************/
/*----------------------------------------------------------------------------*/
#include "common/Mapping.hh"
#include "common/StringConversion.hh"
#include "fusex/stat/Stat.hh"
/*----------------------------------------------------------------------------*/
#include "XrdOuc/XrdOucString.hh"
#include "fmt/printf.h"
/*----------------------------------------------------------------------------*/
static constexpr std::string_view na = "NA";
void
Stat::Add(const char* tag, uid_t uid, gid_t gid, unsigned long val)
{
XrdSysMutexHelper lLock(Mutex);
StatsUid[tag][uid] += val;
StatsGid[tag][gid] += val;
StatAvgUid[tag][uid].Add(val);
StatAvgGid[tag][gid].Add(val);
}
/*----------------------------------------------------------------------------*/
void
Stat::AddExt(const char* tag, uid_t uid, gid_t gid, unsigned long nsample,
const double& avgv, const double& minv, const double& maxv)
{
XrdSysMutexHelper lLock(Mutex);
StatExtUid[tag][uid].Insert(nsample, avgv, minv, maxv);
StatExtGid[tag][gid].Insert(nsample, avgv, minv, maxv);
}
/*----------------------------------------------------------------------------*/
void
Stat::AddExec(const char* tag, float exectime)
{
XrdSysMutexHelper lLock(Mutex);
StatExec[tag].push_back(exectime);
// skip asynchronous calls release / releasedir
if (std::string(tag).substr(0, 7) != "release") {
TotalExec += exectime;
}
// we average over 1000 entries
if (StatExec[tag].size() > 1000) {
StatExec[tag].pop_front();
}
}
/*----------------------------------------------------------------------------*/
unsigned long long
Stat::GetTotal(const char* tag)
{
google::sparse_hash_map::const_iterator it;
unsigned long long val = 0;
if (!StatsUid.count(tag)) {
return 0;
}
for (it = StatsUid[tag].begin(); it != StatsUid[tag].end(); ++it) {
val += it->second;
}
return val;
}
/*----------------------------------------------------------------------------*/
// warning: you have to lock the mutex if directly used
double
Stat::GetTotalAvg3600(const char* tag)
{
google::sparse_hash_map::iterator it;
double val = 0;
if (!StatAvgUid.count(tag)) {
return 0;
}
for (it = StatAvgUid[tag].begin(); it != StatAvgUid[tag].end(); ++it) {
val += it->second.GetAvg3600();
}
return val;
}
/*----------------------------------------------------------------------------*/
// warning: you have to lock the mutex if directly used
double
Stat::GetTotalNExt3600(const char* tag)
{
google::sparse_hash_map::iterator it;
unsigned long n = 0;
if (!StatExtUid.count(tag)) {
return 0;
}
for (it = StatExtUid[tag].begin(); it != StatExtUid[tag].end(); ++it) {
for (int i = 0; i < 3600; i++) {
n += it->second.n3600[i];
}
}
return (double) n;
}
/*----------------------------------------------------------------------------*/
// warning: you have to lock the mutex if directly used
double
Stat::GetTotalAvgExt3600(const char* tag)
{
google::sparse_hash_map::iterator it;
double val = 0;
double totw = 0;
if (!StatExtUid.count(tag)) {
return 0;
}
for (it = StatExtUid[tag].begin(); it != StatExtUid[tag].end(); ++it) {
double w = 0;
for (int i = 0; i < 3600; i++) {
w += it->second.n3600[i];
}
totw += w;
val += it->second.GetAvg3600() * w;
}
return val / totw;
}
/*----------------------------------------------------------------------------*/
// warning: you have to lock the mutex if directly used
double
Stat::GetTotalMinExt3600(const char* tag)
{
google::sparse_hash_map::iterator it;
double minval = (double) std::numeric_limits::max();
if (!StatExtUid.count(tag)) {
return 0;
}
for (it = StatExtUid[tag].begin(); it != StatExtUid[tag].end(); ++it) {
minval = std::min(minval, it->second.GetMin3600());
}
return minval;
}
/*----------------------------------------------------------------------------*/
// warning: you have to lock the mutex if directly used
double
Stat::GetTotalMaxExt3600(const char* tag)
{
google::sparse_hash_map::iterator it;
double maxval = (double) std::numeric_limits::min();
if (!StatExtUid.count(tag)) {
return 0;
}
for (it = StatExtUid[tag].begin(); it != StatExtUid[tag].end(); ++it) {
maxval = std::max(maxval, it->second.GetMax3600());
}
return maxval;
}
/*----------------------------------------------------------------------------*/
// warning: you have to lock the mutex if directly used
double
Stat::GetTotalAvg300(const char* tag)
{
google::sparse_hash_map::iterator it;
double val = 0;
if (!StatAvgUid.count(tag)) {
return 0;
}
for (it = StatAvgUid[tag].begin(); it != StatAvgUid[tag].end(); ++it) {
val += it->second.GetAvg300();
}
return val;
}
/*----------------------------------------------------------------------------*/
// warning: you have to lock the mutex if directly used
double
Stat::GetTotalNExt300(const char* tag)
{
google::sparse_hash_map::iterator it;
unsigned long n = 0;
if (!StatExtUid.count(tag)) {
return 0;
}
for (it = StatExtUid[tag].begin(); it != StatExtUid[tag].end(); ++it) {
for (int i = 0; i < 300; i++) {
n += it->second.n300[i];
}
}
return (double) n;
}
/*----------------------------------------------------------------------------*/
// warning: you have to lock the mutex if directly used
double
Stat::GetTotalAvgExt300(const char* tag)
{
google::sparse_hash_map::iterator it;
double val = 0;
double totw = 0;
if (!StatExtUid.count(tag)) {
return 0;
}
for (it = StatExtUid[tag].begin(); it != StatExtUid[tag].end(); ++it) {
double w = 0;
for (int i = 0; i < 300; i++) {
w += it->second.n300[i];
}
totw += w;
val += it->second.GetAvg300() * w;
}
return val / totw;
}
/*----------------------------------------------------------------------------*/
// warning: you have to lock the mutex if directly used
double
Stat::GetTotalMinExt300(const char* tag)
{
google::sparse_hash_map::iterator it;
double minval = (double) std::numeric_limits::max();
if (!StatExtUid.count(tag)) {
return 0;
}
for (it = StatExtUid[tag].begin(); it != StatExtUid[tag].end(); ++it) {
minval = std::min(minval, it->second.GetMin300());
}
return minval;
}
/*----------------------------------------------------------------------------*/
// warning: you have to lock the mutex if directly used
double
Stat::GetTotalMaxExt300(const char* tag)
{
google::sparse_hash_map::iterator it;
double maxval = (double) std::numeric_limits::min();
if (!StatExtUid.count(tag)) {
return 0;
}
for (it = StatExtUid[tag].begin(); it != StatExtUid[tag].end(); ++it) {
maxval = std::max(maxval, it->second.GetMax300());
}
return maxval;
}
/*----------------------------------------------------------------------------*/
// warning: you have to lock the mutex if directly used
double
Stat::GetTotalAvg60(const char* tag)
{
google::sparse_hash_map::iterator it;
double val = 0;
if (!StatAvgUid.count(tag)) {
return 0;
}
for (it = StatAvgUid[tag].begin(); it != StatAvgUid[tag].end(); ++it) {
val += it->second.GetAvg60();
}
return val;
}
/*----------------------------------------------------------------------------*/
// warning: you have to lock the mutex if directly used
double
Stat::GetTotalNExt60(const char* tag)
{
google::sparse_hash_map::iterator it;
unsigned long n = 0;
if (!StatExtUid.count(tag)) {
return 0;
}
for (it = StatExtUid[tag].begin(); it != StatExtUid[tag].end(); ++it) {
for (int i = 0; i < 60; i++) {
n += it->second.n60[i];
}
}
return (double) n;
}
/*----------------------------------------------------------------------------*/
// warning: you have to lock the mutex if directly used
double
Stat::GetTotalAvgExt60(const char* tag)
{
google::sparse_hash_map::iterator it;
double val = 0;
double totw = 0;
if (!StatExtUid.count(tag)) {
return 0;
}
for (it = StatExtUid[tag].begin(); it != StatExtUid[tag].end(); ++it) {
double w = 0;
for (int i = 0; i < 60; i++) {
w += it->second.n60[i];
}
totw += w;
val += it->second.GetAvg60() * w;
}
return val / totw;
}
/*----------------------------------------------------------------------------*/
// warning: you have to lock the mutex if directly used
double
Stat::GetTotalMinExt60(const char* tag)
{
google::sparse_hash_map::iterator it;
double minval = (double) std::numeric_limits::max();
if (!StatExtUid.count(tag)) {
return 0;
}
for (it = StatExtUid[tag].begin(); it != StatExtUid[tag].end(); ++it) {
minval = std::min(minval, it->second.GetMin60());
}
return minval;
}
/*----------------------------------------------------------------------------*/
// warning: you have to lock the mutex if directly used
double
Stat::GetTotalMaxExt60(const char* tag)
{
google::sparse_hash_map::iterator it;
double maxval = (double) std::numeric_limits::min();
if (!StatExtUid.count(tag)) {
return 0;
}
for (it = StatExtUid[tag].begin(); it != StatExtUid[tag].end(); ++it) {
maxval = std::max(maxval, it->second.GetMax60());
}
return maxval;
}
/*----------------------------------------------------------------------------*/
// warning: you have to lock the mutex if directly used
double
Stat::GetTotalAvg5(const char* tag)
{
google::sparse_hash_map::iterator it;
double val = 0;
if (!StatAvgUid.count(tag)) {
return 0;
}
for (it = StatAvgUid[tag].begin(); it != StatAvgUid[tag].end(); ++it) {
val += it->second.GetAvg5();
}
return val;
}
/*----------------------------------------------------------------------------*/
// warning: you have to lock the mutex if directly used
double
Stat::GetTotalNExt5(const char* tag)
{
google::sparse_hash_map::iterator it;
unsigned long n = 0;
if (!StatExtUid.count(tag)) {
return 0;
}
for (it = StatExtUid[tag].begin(); it != StatExtUid[tag].end(); ++it) {
for (int i = 0; i < 5; i++) {
n += it->second.n5[i];
}
}
return (double) n;
}
/*----------------------------------------------------------------------------*/
// warning: you have to lock the mutex if directly used
double
Stat::GetTotalAvgExt5(const char* tag)
{
google::sparse_hash_map::iterator it;
double val = 0;
double totw = 0;
if (!StatExtUid.count(tag)) {
return 0;
}
for (it = StatExtUid[tag].begin(); it != StatExtUid[tag].end(); ++it) {
double w = 0;
for (int i = 0; i < 5; i++) {
w += it->second.n5[i];
}
totw += w;
val += it->second.GetAvg5() * w;
}
return val / totw;
}
/*----------------------------------------------------------------------------*/
// warning: you have to lock the mutex if directly used
double
Stat::GetTotalMinExt5(const char* tag)
{
google::sparse_hash_map::iterator it;
double minval = (double) std::numeric_limits::max();
if (!StatExtUid.count(tag)) {
return 0;
}
for (it = StatExtUid[tag].begin(); it != StatExtUid[tag].end(); ++it) {
minval = std::min(minval, it->second.GetMin5());
}
return minval;
}
/*----------------------------------------------------------------------------*/
// warning: you have to lock the mutex if directly used
double
Stat::GetTotalMaxExt5(const char* tag)
{
google::sparse_hash_map::iterator it;
double maxval = (double) std::numeric_limits::min();
if (!StatExtUid.count(tag)) {
return 0;
}
for (it = StatExtUid[tag].begin(); it != StatExtUid[tag].end(); ++it) {
maxval = std::max(maxval, it->second.GetMax5());
}
return maxval;
}
/*----------------------------------------------------------------------------*/
// warning: you have to lock the mutex if directly used
double
Stat::GetExec(const char* tag, double& deviation)
{
// calculates average execution time for 'tag'
if (StatExec.count(tag)) {
std::deque::const_iterator it;
double sum = 0;
double avg = 0;
deviation = 0;
int cnt = 0;
for (it = StatExec[tag].begin(); it != StatExec[tag].end(); it++) {
cnt++;
sum += *it;
}
avg = sum / (cnt ? cnt : 999999999);
for (it = StatExec[tag].begin(); it != StatExec[tag].end(); it++) {
deviation += pow((*it - avg), 2);
}
deviation = sqrt(deviation / (cnt ? cnt : 99999999));
return avg;
}
return 0;
}
/*----------------------------------------------------------------------------*/
// warning: you have to lock the mutex if directly used
/*----------------------------------------------------------------------------*/
double
Stat::GetTotalExec(double& deviation, size_t& ops)
{
// calculates average execution time for all commands
google::sparse_hash_map >::const_iterator ittag;
double sum = 0;
double avg = 0;
size_t cnt = 0;
deviation = 0;
for (ittag = StatExec.begin(); ittag != StatExec.end(); ittag++) {
std::deque::const_iterator it;
for (it = ittag->second.begin(); it != ittag->second.end(); it++) {
cnt++;
sum += *it;
}
ops += GetTotal(ittag->first.c_str());
}
if (cnt) {
avg = sum / cnt;
}
for (ittag = StatExec.begin(); ittag != StatExec.end(); ittag++) {
std::deque::const_iterator it;
for (it = ittag->second.begin(); it != ittag->second.end(); it++) {
deviation += pow((*it - avg), 2);
}
}
if (cnt) {
deviation = sqrt(deviation / cnt);
}
return avg;
}
/*----------------------------------------------------------------------------*/
void
Stat::Clear()
{
XrdSysMutexHelper lLock(Mutex);
for (auto ittag = StatsUid.begin(); ittag != StatsUid.end(); ittag++) {
StatsUid[ittag->first].clear();
StatsUid[ittag->first].resize(1000);
}
for (auto ittag = StatsGid.begin(); ittag != StatsGid.end(); ittag++) {
StatsGid[ittag->first].clear();
StatsGid[ittag->first].resize(1000);
}
for (auto ittag = StatsUid.begin(); ittag != StatsUid.end(); ittag++) {
StatAvgUid[ittag->first].clear();
StatAvgUid[ittag->first].resize(1000);
}
for (auto ittag = StatsGid.begin(); ittag != StatsGid.end(); ittag++) {
StatAvgGid[ittag->first].clear();
StatAvgGid[ittag->first].resize(1000);
}
for (auto ittag = StatExec.begin(); ittag != StatExec.end(); ittag++) {
StatExec[ittag->first].clear();
StatExec[ittag->first].resize(1000);
}
TotalExec = 0;
}
/*----------------------------------------------------------------------------*/
void
Stat::PrintOutTotal(std::string& out, bool details, bool monitoring,
bool numerical)
{
XrdSysMutexHelper lLock(Mutex);
std::vector tags, tags_ext;
std::vector::iterator it;
google::sparse_hash_map >::iterator
tit;
google::sparse_hash_map >::iterator
tit_ext;
for (tit = StatsUid.begin(); tit != StatsUid.end(); tit++) {
tags.push_back(tit->first);
}
for (tit_ext = StatExtUid.begin(); tit_ext != StatExtUid.end(); tit_ext++) {
tags_ext.push_back(tit_ext->first);
}
std::sort(tags.begin(), tags.end());
std::sort(tags_ext.begin(), tags_ext.end());
char outline[8192];
double avg = 0;
double sig = 0;
size_t ops = 0;
avg = GetTotalExec(sig, ops);
sum_ops = ops;
if (!monitoring) {
snprintf(outline, sizeof(outline),
"%-7s %-32s %3.02f +- %3.02f = %.02fs (%lu ops)\n", "ALL",
"Execution Time", avg,
sig, TotalExec / 1000.0, ops);
out += outline;
out += "# -----------------------------------------------------------------------------------------------------------------------\n";
snprintf(outline, sizeof(outline),
"%-7s %-32s %-9s %8s %8s %8s %8s %-8s +- %-10s = %-10s", "who",
"command", "sum", "5s", "1min", "5min", "1h", "exec(ms)", "sigma(ms)",
"cumul(s)");
out += outline;
out += "\n";
out += "# -----------------------------------------------------------------------------------------------------------------------\n";
} else {
snprintf(outline, sizeof(outline),
"uid=all gid=all total.exec.avg=%.02f total.exec.sigma=%.02f total.exec.sum=%.02f\n",
avg, sig, TotalExec);
out += outline;
}
for (it = tags.begin(); it != tags.end(); ++it) {
if ((*it == "rbytes") || (*it == "wbytes")) {
continue;
}
const char* tag = it->c_str();
std::string aexec = "-NA-";
std::string aexecsig = "-NA-";
double avg = 0;
double sig = 0;
double total = 0;
avg = GetExec(tag, sig);
std::string a5 = fmt::sprintf("%3.02f", GetTotalAvg5(tag));
std::string a60 = fmt::sprintf("%3.02f", GetTotalAvg60(tag));
std::string a300 = fmt::sprintf("%3.02f", GetTotalAvg300(tag));
std::string a3600 = fmt::sprintf("%3.02f", GetTotalAvg3600(tag));
if (avg) {
aexec = fmt::sprintf("%3.05f", avg);
}
if (sig) {
aexecsig = fmt::sprintf("%3.05f", sig);
}
total = avg * GetTotal(tag) / 1000.0;
std::string atotal = fmt::sprintf("%04.02f", total);
// TODO: make the template a constexpr sv so that it is easier to validate
if (!monitoring) {
out += fmt::sprintf("ALL %-32s %12llu %8s %8s %8s %8s %8s +- %-10s = %-10s\n",
tag, GetTotal(tag), a5, a60, a300, a3600, aexec, aexecsig, atotal);
} else {
out += fmt::sprintf("uid=all gid=all cmd=%s total=%llu 5s=%s 60s=%s 300s=%s 3600s=%s exec=%f execsig=%f cumulated=%f\n",
tag, GetTotal(tag), a5, a60, a300, a3600, avg, sig, total);
}
}
for (it = tags_ext.begin(); it != tags_ext.end(); ++it) {
const char* tag = it->c_str();
double nsample;
std::string n5, a5{na}, m5{na}, M5{na};
std::string n60, a60{na}, m60{na}, M60{na};
std::string n300, a300{na}, m300{na}, M300{na};
std::string n3600, a3600{na}, m3600{na}, M3600{na};
if ((nsample = GetTotalNExt5(tag)) < 1) {
n5 = fmt::sprintf("%6.01e", nsample);
} else {
n5 = fmt::sprintf("%6.01e", nsample);
a5 = fmt::sprintf("%6.01e", GetTotalAvgExt5(tag));
m5 = fmt::sprintf("%6.01e", GetTotalMinExt5(tag));
M5 = fmt::sprintf("%6.01e", GetTotalMaxExt5(tag));
}
if ((nsample = GetTotalNExt60(tag)) < 1) {
n60 = fmt::sprintf("%6.01e", nsample);
} else {
n60 = fmt::sprintf("%6.01e", nsample);
a60 = fmt::sprintf("%6.01e", GetTotalAvgExt60(tag));
m60 = fmt::sprintf("%6.01e", GetTotalMinExt60(tag));
M60 = fmt::sprintf("%6.01e", GetTotalMaxExt60(tag));
}
if ((nsample = GetTotalNExt300(tag)) < 1) {
n300 = fmt::sprintf("%6.01e", nsample);
} else {
n300 = fmt::sprintf("%6.01e", nsample);
a300 = fmt::sprintf("%6.01e", GetTotalAvgExt300(tag));
m300 = fmt::sprintf("%6.01e", GetTotalMinExt300(tag));
M300 = fmt::sprintf("%6.01e", GetTotalMaxExt300(tag));
}
if ((nsample = GetTotalNExt3600(tag)) < 1) {
n3600 = fmt::sprintf("%6.01e", nsample);
} else {
n3600 = fmt::sprintf("%6.01e", GetTotalNExt3600(tag));
a3600 = fmt::sprintf("%6.01e", GetTotalAvgExt3600(tag));
m3600 = fmt::sprintf("%6.01e", GetTotalMinExt3600(tag));
M3600 = fmt::sprintf("%6.01e", GetTotalMaxExt3600(tag));
}
if (details) {
if (!monitoring) {
out += fmt::sprintf("ALL %-32s %12s %8s %8s %8s %8s\n", tag, "spl", n5, n60,
n300, n3600);
out += fmt::sprintf("ALL %-32s %12s %8s %8s %8s %8s\n", tag, "min", m5, m60,
m300, m3600);
out += fmt::sprintf("ALL %-32s %12s %8s %8s %8s %8s\n", tag, "avg", a5, a60,
a300, a3600);
out += fmt::sprintf("ALL %-32s %12s %8s %8s %8s %8s\n", tag, "max", M5, M60,
M300, M3600);
} else {
out += fmt::sprintf("uid=all gid=all cmd=%s:spl 5s=%s 60s=%s 300s=%s 3600s=%s\n",
tag, n5, n60, n300, n3600);
out += fmt::sprintf("uid=all gid=all cmd=%s:min 5s=%s 60s=%s 300s=%s 3600s=%s\n",
tag, m5, m60, m300, m3600);
out += fmt::sprintf("uid=all gid=all cmd=%s:avg 5s=%s 60s=%s 300s=%s 3600s=%s\n",
tag, a5, a60, a300, a3600);
out += fmt::sprintf("uid=all gid=all cmd=%s:max 5s=%s 60s=%s 300s=%s 3600s=%s\n",
tag, M5, M60, M300, M3600);
}
}
}
if (details) {
google::sparse_hash_map >::iterator
tuit;
google::sparse_hash_map >::iterator
tgit;
google::sparse_hash_map >::iterator
tuit_ext;
google::sparse_hash_map >::iterator
tgit_ext;
std::map umap;
std::map gmap;
for (tuit = StatAvgUid.begin(); tuit != StatAvgUid.end(); tuit++) {
google::sparse_hash_map::iterator it;
for (it = tuit->second.begin(); it != tuit->second.end(); ++it) {
int terrc = 0;
std::string username = eos::common::Mapping::UidToUserName(it->first, terrc);
umap[it->first] = username;
}
}
for (tuit_ext = StatExtUid.begin(); tuit_ext != StatExtUid.end(); tuit_ext++) {
google::sparse_hash_map::iterator it;
for (it = tuit_ext->second.begin(); it != tuit_ext->second.end(); ++it) {
int terrc = 0;
std::string username = eos::common::Mapping::UidToUserName(it->first, terrc);
umap[it->first] = username;
}
}
for (tgit = StatAvgGid.begin(); tgit != StatAvgGid.end(); tgit++) {
google::sparse_hash_map::iterator it;
for (it = tgit->second.begin(); it != tgit->second.end(); ++it) {
int terrc = 0;
std::string groupname = eos::common::Mapping::GidToGroupName(it->first, terrc);
gmap[it->first] = groupname;
}
}
for (tgit_ext = StatExtGid.begin(); tgit_ext != StatExtGid.end(); tgit_ext++) {
google::sparse_hash_map::iterator it;
for (it = tgit_ext->second.begin(); it != tgit_ext->second.end(); ++it) {
int terrc = 0;
std::string groupname = eos::common::Mapping::GidToGroupName(it->first, terrc);
gmap[it->first] = groupname;
}
}
if (!monitoring) {
out += "# -----------------------------------------------------------------------------------------------------------------------\n";
}
std::vector uidout;
std::vector gidout;
std::string _outline;
for (tuit = StatAvgUid.begin(); tuit != StatAvgUid.end(); tuit++) {
google::sparse_hash_map::iterator it;
for (it = tuit->second.begin(); it != tuit->second.end(); ++it) {
std::string a5 = fmt::sprintf("%3.02f", it->second.GetAvg5());
std::string a60 = fmt::sprintf("%3.02f", it->second.GetAvg60());;
std::string a300 = fmt::sprintf("%3.02f", it->second.GetAvg300());;
std::string a3600 = fmt::sprintf("%3.02f", it->second.GetAvg3600());
std::string identifier;
if (numerical) {
identifier = fmt::sprintf("uid=%d", it->first);
} else {
std::string username = umap.count(it->first) ? umap[it->first] :
eos::common::StringConversion::GetSizeString(username,
(unsigned long long) it->first);
if (monitoring) {
identifier = fmt::sprintf("uid=%s", username);
} else {
identifier = fmt::sprintf("%s", username);
}
}
if (!monitoring) {
_outline = fmt::sprintf("%-10s %-32s %12llu %8s %8s %8s %8s\n", identifier,
tuit->first, StatsUid[tuit->first.c_str()][it->first], a5, a60, a300,
a3600);
} else {
_outline = fmt::sprintf("%s cmd=%s total=%llu 5s=%s 60s=%s 300s=%s 3600s=%s\n",
identifier, tuit->first, StatsUid[tuit->first.c_str()][it->first], a5,
a60, a300, a3600);
}
uidout.emplace_back(std::move(_outline));
}
}
std::sort(uidout.begin(), uidout.end());
std::vector::iterator sit;
for (sit = uidout.begin(); sit != uidout.end(); sit++) {
out += sit->c_str();
}
uidout.clear();
for (tuit_ext = StatExtUid.begin(); tuit_ext != StatExtUid.end(); tuit_ext++) {
google::sparse_hash_map::iterator it;
for (it = tuit_ext->second.begin(); it != tuit_ext->second.end(); ++it) {
const char* tag = tuit_ext->first.c_str();
double nsample;
std::string n5, a5{na}, m5{na}, M5{na};
std::string n60, a60{na}, m60{na}, M60{na};
std::string n300, a300{na}, m300{na}, M300{na};
std::string n3600, a3600{na}, m3600{na}, M3600{na};
if ((nsample = it->second.GetN5()) < 1) {
n5 = fmt::sprintf("%6.01e", nsample);
} else {
n5 = fmt::sprintf("%6.01e", nsample);
a5 = fmt::sprintf("%6.01e", it->second.GetAvg5());
m5 = fmt::sprintf("%6.01e", it->second.GetMin5());
M5 = fmt::sprintf("%6.01e", it->second.GetMax5());
}
if ((nsample = it->second.GetN60()) < 1) {
n60 = fmt::sprintf("%6.01e", nsample);
} else {
n60 = fmt::sprintf("%6.01e", nsample);
a60 = fmt::sprintf("%6.01e", it->second.GetAvg60());
m60 = fmt::sprintf("%6.01e", it->second.GetMin60());
M60 = fmt::sprintf("%6.01e", it->second.GetMax60());
}
if ((nsample = it->second.GetN300()) < 1) {
n300 = fmt::sprintf("%6.01e", nsample);
} else {
n300 = fmt::sprintf("%6.01e", nsample);
a300 = fmt::sprintf("%6.01e", it->second.GetAvg300());
m300 = fmt::sprintf("%6.01e", it->second.GetMin300());
M300 = fmt::sprintf("%6.01e", it->second.GetMax300());
}
if ((nsample = it->second.GetN3600()) < 1) {
n3600 = fmt::sprintf("%6.01e", nsample);
} else {
n3600 = fmt::sprintf("%6.01e", nsample);
a3600 = fmt::sprintf("%6.01e", it->second.GetAvg3600());
m3600 = fmt::sprintf("%6.01e", it->second.GetMin3600());
M3600 = fmt::sprintf("%6.01e", it->second.GetMax3600());
}
char identifier[1024];
if (numerical) {
snprintf(identifier, 1023, "uid=%d", it->first);
} else {
std::string username = umap.count(it->first) ? umap[it->first] :
eos::common::StringConversion::GetSizeString(username,
(unsigned long long) it->first);
if (monitoring) {
snprintf(identifier, 1023, "uid=%s", username.c_str());
} else {
snprintf(identifier, 1023, "%s", username.c_str());
}
}
if (!monitoring) {
out += fmt::sprintf("%-10s %-32s %12s %8s %8s %8s %8s\n", identifier, tag,
"spl",
n5, n60, n300, n3600);
out += fmt::sprintf("%-10s %-32s %12s %8s %8s %8s %8s\n", identifier, tag,
"min",
m5, m60, m300, m3600);
out += fmt::sprintf("%-10s %-32s %12s %8s %8s %8s %8s\n", identifier, tag,
"avg",
a5, a60, a300, a3600);
out += fmt::sprintf("%-10s %-32s %12s %8s %8s %8s %8s\n", identifier, tag,
"max",
M5, M60, M300, M3600);
} else {
out += fmt::sprintf("%s cmd=%s:spl 5s=%s 60s=%s 300s=%s 3600s=%s\n", identifier,
tag, n5, n60, n300, n3600);
out += fmt::sprintf("%s cmd=%s:min 5s=%s 60s=%s 300s=%s 3600s=%s\n", identifier,
tag, m5, m60, m300, m3600);
out += fmt::sprintf("%s cmd=%s:avg 5s=%s 60s=%s 300s=%s 3600s=%s\n", identifier,
tag, a5, a60, a300, a3600);
out += fmt::sprintf("%s cmd=%s:max 5s=%s 60s=%s 300s=%s 3600s=%s\n", identifier,
tag, M5, M60, M300, M3600);
}
}
}
std::sort(uidout.begin(), uidout.end());
for (sit = uidout.begin(); sit != uidout.end(); sit++) {
out += sit->c_str();
}
if (!monitoring) {
out += "# --------------------------------------------------------------------------------------\n";
}
for (tgit = StatAvgGid.begin(); tgit != StatAvgGid.end(); tgit++) {
google::sparse_hash_map::iterator it;
for (it = tgit->second.begin(); it != tgit->second.end(); ++it) {
std::string a5 = fmt::sprintf("%3.02f", it->second.GetAvg5());
std::string a60 = fmt::sprintf("%3.02f", it->second.GetAvg60());;
std::string a300 = fmt::sprintf("%3.02f", it->second.GetAvg300());;
std::string a3600 = fmt::sprintf("%3.02f", it->second.GetAvg3600());
char identifier[1024];
if (numerical) {
snprintf(identifier, 1023, "gid=%d", it->first);
} else {
std::string groupname = gmap.count(it->first) ? gmap[it->first] :
eos::common::StringConversion::GetSizeString(groupname,
(unsigned long long) it->first);
if (monitoring) {
snprintf(identifier, 1023, "gid=%s", groupname.c_str());
} else {
snprintf(identifier, 1023, "%s", groupname.c_str());
}
}
if (!monitoring) {
_outline = fmt::sprintf("%-10s %-32s %12llu %8s %8s %8s %8s\n", identifier,
tgit->first, StatsGid[tgit->first.c_str()][it->first], a5, a60, a300,
a3600);
} else {
_outline = fmt::sprintf("%s cmd=%s total=%llu 5s=%s 60s=%s 300s=%s 3600s=%s\n",
identifier, tgit->first, StatsUid[tgit->first.c_str()][it->first], a5,
a60, a300, a3600);
}
gidout.emplace_back(std::move(_outline));
}
}
std::sort(gidout.begin(), gidout.end());
for (sit = gidout.begin(); sit != gidout.end(); sit++) {
out += sit->c_str();
}
gidout.clear();
for (tgit_ext = StatExtGid.begin(); tgit_ext != StatExtGid.end(); tgit_ext++) {
google::sparse_hash_map::iterator it;
for (it = tgit_ext->second.begin(); it != tgit_ext->second.end(); ++it) {
double nsample;
const char na[9] = "NA";
char n5[1024], a5[1024], m5[1024], M5[1024];
char n60[1024], a60[1024], m60[1024], M60[1024];
char n300[1024], a300[1024], m300[1024], M300[1024];
char n3600[1024], a3600[1024], m3600[1024], M3600[1024];
if ((nsample = it->second.GetN5()) < 1) {
strcpy(a5, na);
strcpy(m5, na);
strcpy(M5, na);
sprintf(n5, "%6.01e", nsample);
} else {
sprintf(n5, "%6.01e", nsample);
sprintf(a5, "%6.01e", it->second.GetAvg5());
sprintf(m5, "%6.01e", it->second.GetMin5());
sprintf(M5, "%6.01e", it->second.GetMax5());
}
if ((nsample = it->second.GetN60()) < 1) {
strcpy(a60, na);
strcpy(m60, na);
strcpy(M60, na);
sprintf(n60, "%6.01e", nsample);
} else {
sprintf(n60, "%6.01e", nsample);
sprintf(a60, "%6.01e", it->second.GetAvg60());
sprintf(m60, "%6.01e", it->second.GetMin60());
sprintf(M60, "%6.01e", it->second.GetMax60());
}
if ((nsample = it->second.GetN300()) < 1) {
strcpy(a300, na);
strcpy(m300, na);
strcpy(M300, na);
sprintf(n300, "%6.01e", nsample);
} else {
sprintf(n300, "%6.01e", nsample);
sprintf(a300, "%6.01e", it->second.GetAvg300());
sprintf(m300, "%6.01e", it->second.GetMin300());
sprintf(M300, "%6.01e", it->second.GetMax300());
}
if ((nsample = it->second.GetN3600()) < 1) {
strcpy(a3600, na);
strcpy(m3600, na);
strcpy(M3600, na);
sprintf(n3600, "%6.01e", nsample);
} else {
sprintf(n3600, "%6.01e", nsample);
sprintf(a3600, "%6.01e", it->second.GetAvg3600());
sprintf(m3600, "%6.01e", it->second.GetMin3600());
sprintf(M3600, "%6.01e", it->second.GetMax3600());
}
char identifier[1024];
if (numerical) {
snprintf(identifier, 1023, "gid=%d", it->first);
} else {
std::string groupname = gmap.count(it->first) ? gmap[it->first] :
eos::common::StringConversion::GetSizeString(groupname,
(unsigned long long) it->first);
if (monitoring) {
snprintf(identifier, 1023, "gid=%s", groupname.c_str());
} else {
snprintf(identifier, 1023, "%s", groupname.c_str());
}
}
}
}
std::sort(gidout.begin(), gidout.end());
for (sit = gidout.begin(); sit != gidout.end(); sit++) {
out += sit->c_str();
}
if (!monitoring) {
out += "# --------------------------------------------------------------------------------------\n";
}
}
}
void
Stat::PrintOutTotalJson(Json::Value& out)
{
XrdSysMutexHelper lLock(Mutex);
std::vector tags, tags_ext;
std::vector::iterator it;
google::sparse_hash_map >::iterator
tit;
google::sparse_hash_map >::iterator
tit_ext;
for (tit = StatsUid.begin(); tit != StatsUid.end(); tit++) {
tags.push_back(tit->first);
}
for (tit_ext = StatExtUid.begin(); tit_ext != StatExtUid.end(); tit_ext++) {
tags_ext.push_back(tit_ext->first);
}
std::sort(tags.begin(), tags.end());
std::sort(tags_ext.begin(), tags_ext.end());
double avg = 0;
double sig = 0;
size_t ops = 0;
avg = GetTotalExec(sig, ops);
sum_ops = ops;
out["time"]=Json::Value{};
out["time"]["avg(ms)"] = Json::Value(avg);
out["time"]["sigma(ms)"] = Json::Value(sig);
out["time"]["total(s)"] = Json::Value((double) (TotalExec / 1000.0));
out["time"]["ops"] = Json::LargestUInt(sum_ops);
out["activity"] = Json::Value(Json::arrayValue);
for (it = tags.begin(); it != tags.end(); ++it) {
if ((*it == "rbytes") || (*it == "wbytes")) {
continue;
}
Json::Value entry{};
const char* tag = it->c_str();
avg = 0;
sig = 0;
double total = 0;
avg = GetExec(tag, sig);
total = avg * GetTotal(tag) / 1000.0;
entry["command"] = tag;
entry["sum"] = (Json::LargestUInt) GetTotal(tag);
entry["5s"] = GetTotalAvg5(tag);
entry["1min"] = GetTotalAvg60(tag);
entry["5min"] = GetTotalAvg300(tag);
entry["1h"] = GetTotalAvg3600(tag);
entry["exec(ms)"] = avg;
entry["sigma(ms)"] = sig;
entry["cumul(s)"] = total;
out["activity"].append(entry);
}
}
/*----------------------------------------------------------------------------*/
void
Stat::Circulate(ThreadAssistant& assistant)
{
// empty the circular buffer and extract some Mq statistic values
while (true) {
assistant.wait_for(std::chrono::milliseconds(512));
if (assistant.terminationRequested()) {
break;
}
// --------------------------------------------
XrdSysMutexHelper lLock(Mutex);
google::sparse_hash_map >::iterator
tit;
google::sparse_hash_map >::iterator
tit_ext;
// loop over tags
for (tit = StatAvgUid.begin(); tit != StatAvgUid.end(); ++tit) {
// loop over vids
google::sparse_hash_map::iterator it;
for (it = tit->second.begin(); it != tit->second.end(); ++it) {
it->second.StampZero();
}
}
for (tit = StatAvgGid.begin(); tit != StatAvgGid.end(); ++tit) {
// loop over vids
google::sparse_hash_map::iterator it;
for (it = tit->second.begin(); it != tit->second.end(); ++it) {
it->second.StampZero();
}
}
for (tit_ext = StatExtGid.begin(); tit_ext != StatExtGid.end(); ++tit_ext) {
// loop over vids
google::sparse_hash_map::iterator it;
for (it = tit_ext->second.begin(); it != tit_ext->second.end(); ++it) {
it->second.StampZero();
}
}
for (tit_ext = StatExtGid.begin(); tit_ext != StatExtGid.end(); ++tit_ext) {
// loop over vids
google::sparse_hash_map::iterator it;
for (it = tit_ext->second.begin(); it != tit_ext->second.end(); ++it) {
it->second.StampZero();
}
}
}
}