//------------------------------------------------------------------------------
// Author: Andrey Kuznetsov
// Description: Representer of statistics
// Copyright (c) 2015 EPAM Systems
//------------------------------------------------------------------------------
/*
This file is part of Nfstrace.
Nfstrace 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, version 2 of the License.
Nfstrace 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 Nfstrace. If not, see .
*/
//------------------------------------------------------------------------------
#include
#include
#include
#include "representer.h"
//------------------------------------------------------------------------------
using namespace NST::breakdown;
//------------------------------------------------------------------------------
NST::breakdown::Representer::Representer(std::ostream& o, NST::breakdown::CommandRepresenter* cmd_representer, size_t space_for_cmd_name)
: out(o)
, cmd_representer(cmd_representer)
, space_for_cmd_name(space_for_cmd_name)
{
}
void Representer::flush_statistics(const Statistics& statistics)
{
out << "### Breakdown analyzer ###" << std::endl
<< cmd_representer->protocol_name() << " protocol";
if(statistics.has_session())
{
out << std::endl;
statistics.for_each_procedure([&](const BreakdownCounter& breakdown, size_t procedure) {
onProcedureInfoPrinted(out, breakdown, procedure);
size_t procedure_count = breakdown[procedure].get_count();
out.width(space_for_cmd_name);
out << std::left
<< cmd_representer->command_name(procedure);
out.width(5);
out << std::right
<< procedure_count;
out.width(7);
out.setf(std::ios::fixed, std::ios::floatfield);
out.precision(2);
out << (breakdown.get_total_count() ? ((1.0 * procedure_count / breakdown.get_total_count()) * 100.0) : 0);
out.setf(std::ios::fixed | std::ios::scientific, std::ios::floatfield);
out << '%' << std::endl;
});
out << "Per connection info: " << std::endl;
statistics.for_each_session([&](const Session& session) {
std::stringstream ssession;
print_session(ssession, session);
print_per_session(statistics, session, ssession.str());
std::ofstream file("breakdown_" + ssession.str() + ".dat", std::ios::out | std::ios::trunc);
store_per_session(file, statistics, session, ssession.str());
});
}
else
{
out << ": Data transmission has not been detected." << std::endl;
}
}
void Representer::store_per_session(std::ostream& file, const Statistics& statistics, const Session& session, const std::string& ssession) const
{
//TODO: does it make sense to join store_per_session & print_per_session?
file << "Session: " << ssession << std::endl;
statistics.for_each_procedure_in_session(session, [&](const BreakdownCounter& breakdown, size_t procedure) {
uint64_t s_total_proc = breakdown.get_total_count();
file << cmd_representer->command_name(procedure);
file << ' ' << breakdown[procedure].get_count() << ' ';
file << (s_total_proc ? (((long double)(breakdown[procedure].get_count()) / s_total_proc) * 100) : 0);
file << ' ' << to_sec(breakdown[procedure].get_min())
<< ' ' << to_sec(breakdown[procedure].get_max())
<< ' ' << breakdown[procedure].get_avg()
<< ' ' << breakdown[procedure].get_st_dev()
<< std::endl;
});
}
void Representer::print_per_session(const Statistics& statistics, const Session& session, const std::string& ssession) const
{
out << "Session: " << ssession << std::endl;
statistics.for_each_procedure_in_session(session, [&](const BreakdownCounter& breakdown, size_t procedure) {
uint64_t s_total_proc = breakdown.get_total_count();
onProcedureInfoPrinted(out, breakdown, procedure);
out.width(22);
out << std::left
<< cmd_representer->command_name(procedure);
out.width(6);
out << " Count:";
out.width(5);
out << std::right
<< breakdown[procedure].get_count()
<< ' ';
out.precision(2);
out << '(';
out.width(6);
out << std::fixed
<< (s_total_proc ? (static_cast(breakdown[procedure].get_count()) * 100 / s_total_proc) : 0);
out << "%) Min: ";
out.precision(3);
out << std::fixed
<< to_sec(breakdown[procedure].get_min())
<< " Max: "
<< std::fixed
<< to_sec(breakdown[procedure].get_max())
<< " Avg: "
<< std::fixed
<< breakdown[procedure].get_avg();
out.precision(8);
out << " StDev: "
<< std::fixed
<< breakdown[procedure].get_st_dev()
<< std::endl;
});
}
void Representer::onProcedureInfoPrinted(std::ostream& o, const BreakdownCounter& breakdown, unsigned procedure) const
{
if(procedure == 0)
{
o << "Total operations: " << breakdown.get_total_count()
<< ". Per operation:" << std::endl;
}
}
//------------------------------------------------------------------------------