Ref T698, write network statistics as file when logged off from network

* enum to string (VatClientQueryType)
* also trace calls in "chronological order"
* added some more "increaseStatisticsValue" calls
This commit is contained in:
Klaus Basan
2019-07-06 00:20:24 +02:00
committed by Mat Sutcliffe
parent 419b837b65
commit a5a6a111e1
4 changed files with 121 additions and 20 deletions

View File

@@ -7,6 +7,8 @@
*/ */
#include "network.h" #include "network.h"
#include "blackmisc/fileutils.h"
#include "blackmisc/directoryutils.h"
#include "blackmisc/logmessage.h" #include "blackmisc/logmessage.h"
#include "blackmisc/range.h" #include "blackmisc/range.h"
#include "blackconfig/buildconfig.h" #include "blackconfig/buildconfig.h"
@@ -33,11 +35,19 @@ namespace BlackCore
} }
} }
INetwork::~INetwork()
{ }
int INetwork::increaseStatisticsValue(const QString &identifier, const QString &appendix) int INetwork::increaseStatisticsValue(const QString &identifier, const QString &appendix)
{ {
if (identifier.isEmpty() || !m_statistics) { return -1; } if (identifier.isEmpty() || !m_statistics) { return -1; }
int &v = appendix.isEmpty() ? m_callStatistics[identifier] : m_callStatistics[identifier % u"." % appendix]; const QString i = appendix.isEmpty() ? identifier : identifier % u"." % appendix;
int &v = m_callStatistics[i];
v++; v++;
constexpr int MaxTimeValues = 50;
m_callByTime.push_front(QPair<qint64, QString>(QDateTime::currentMSecsSinceEpoch(), i));
if (m_callByTime.size() > MaxTimeValues) { m_callByTime.removeLast(); }
return v; return v;
} }
@@ -46,17 +56,23 @@ namespace BlackCore
return this->increaseStatisticsValue(identifier, QString::number(value)); return this->increaseStatisticsValue(identifier, QString::number(value));
} }
void INetwork::clearStatistics()
{
m_callStatistics.clear();
m_callByTime.clear();
}
QString INetwork::getNetworkStatisticsAsText(bool reset, const QString &separator) QString INetwork::getNetworkStatisticsAsText(bool reset, const QString &separator)
{ {
QVector<std::pair<int, QString>> transformed; QVector<std::pair<int, QString>> transformed;
if (m_callStatistics.isEmpty()) { return QString(); }
for (const auto pair : makePairsRange(as_const(m_callStatistics))) for (const auto pair : makePairsRange(as_const(m_callStatistics)))
{ {
// key is pair.first, value is pair.second // key is pair.first, value is pair.second
transformed.push_back({ pair.second, pair.first }); transformed.push_back({ pair.second, pair.first });
} }
if (reset) { this->clearStatistics(); }
// sorted by value // sorted by value
std::sort(transformed.begin(), transformed.end(), std::greater<>()); std::sort(transformed.begin(), transformed.end(), std::greater<>());
QString stats; QString stats;
@@ -66,7 +82,37 @@ namespace BlackCore
(stats.isEmpty() ? QString() : separator) % (stats.isEmpty() ? QString() : separator) %
pair.second % u": " % QString::number(pair.first); pair.second % u": " % QString::number(pair.first);
} }
for (const auto &pair : transformed)
{
stats +=
(stats.isEmpty() ? QString() : separator) %
pair.second % u": " % QString::number(pair.first);
}
if (!m_callByTime.isEmpty())
{
const qint64 lastTs = m_callByTime.front().first;
for (const auto &pair : m_callByTime)
{
const qint64 deltaTs = lastTs - pair.first;
stats += separator % QStringLiteral("%1").arg(deltaTs, 5, 10, QChar('0')) % u": " % pair.second;
}
}
if (reset) { this->clearStatistics(); }
return stats; return stats;
} }
bool INetwork::saveNetworkStatistics(const QString &server)
{
if (m_callStatistics.isEmpty()) { return false; }
const QString s = this->getNetworkStatisticsAsText(false, "\n");
if (s.isEmpty()) { return false; }
const QString fn = QStringLiteral("networkstatistics_%1_%2.log").arg(QDateTime::currentDateTimeUtc().toString("yyMMddhhmmss"), server);
const QString fp = CFileUtils::appendFilePaths(CDirectoryUtils::logDirectory(), fn);
return CFileUtils::writeStringToFile(s, fp);
}
} // ns } // ns

View File

@@ -80,7 +80,7 @@ namespace BlackCore
public: public:
//! Destructor //! Destructor
virtual ~INetwork() {} virtual ~INetwork();
//! Underlying library info. //! Underlying library info.
virtual const QString &getLibraryInfo(bool detailed) const = 0; virtual const QString &getLibraryInfo(bool detailed) const = 0;
@@ -117,7 +117,7 @@ namespace BlackCore
//! @} //! @}
//! Clear the statistics //! Clear the statistics
void clearStatistics() { m_callStatistics.clear(); } void clearStatistics();
//! Text statistics //! Text statistics
QString getNetworkStatisticsAsText(bool reset, const QString &separator = "\n"); QString getNetworkStatisticsAsText(bool reset, const QString &separator = "\n");
@@ -599,9 +599,14 @@ namespace BlackCore
//! @} //! @}
protected:
//! Save the statistics
bool saveNetworkStatistics(const QString &server);
private: private:
bool m_statistics = false; bool m_statistics = false;
QMap <QString, int> m_callStatistics; QMap <QString, int> m_callStatistics;
QVector <QPair<qint64, QString>> m_callByTime;
}; };
} // namespace } // namespace

View File

@@ -305,6 +305,7 @@ namespace BlackCore
this->clearState(); this->clearState();
this->setLastEcosystem(m_server.getEcosystem()); this->setLastEcosystem(m_server.getEcosystem());
this->setCurrentEcosystem(CEcosystem::NoSystem); this->setCurrentEcosystem(CEcosystem::NoSystem);
this->saveNetworkStatistics(m_server.getName());
} }
emit this->connectionStatusChanged(convertConnectionStatus(status), convertConnectionStatus(m_status)); emit this->connectionStatusChanged(convertConnectionStatus(status), convertConnectionStatus(m_status));
@@ -627,7 +628,7 @@ namespace BlackCore
Vat_SendClientQuery(m_net.data(), vatClientQueryIP, nullptr); Vat_SendClientQuery(m_net.data(), vatClientQueryIP, nullptr);
// statistics // statistics
this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery")); this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), enumToString(vatClientQueryIP));
} }
void CNetworkVatlib::sendFrequencyQuery(const CCallsign &callsign) void CNetworkVatlib::sendFrequencyQuery(const CCallsign &callsign)
@@ -636,7 +637,7 @@ namespace BlackCore
Vat_SendClientQuery(m_net.data(), vatClientQueryFreq, toFSD(callsign)); Vat_SendClientQuery(m_net.data(), vatClientQueryFreq, toFSD(callsign));
// statistics // statistics
this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), vatClientQueryFreq); this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), enumToString(vatClientQueryFreq));
} }
void CNetworkVatlib::sendUserInfoQuery(const CCallsign &callsign) void CNetworkVatlib::sendUserInfoQuery(const CCallsign &callsign)
@@ -645,7 +646,7 @@ namespace BlackCore
Vat_SendClientQuery(m_net.data(), vatClientQueryInfo, toFSD(callsign)); Vat_SendClientQuery(m_net.data(), vatClientQueryInfo, toFSD(callsign));
// statistics // statistics
this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), vatClientQueryInfo); this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), enumToString(vatClientQueryInfo));
} }
void CNetworkVatlib::setInterimPositionReceivers(const CCallsignSet &receivers) void CNetworkVatlib::setInterimPositionReceivers(const CCallsignSet &receivers)
@@ -677,7 +678,7 @@ namespace BlackCore
Vat_SendClientQuery(m_net.data(), vatClientQueryServer, toFSD(callsign)); Vat_SendClientQuery(m_net.data(), vatClientQueryServer, toFSD(callsign));
// statistics // statistics
this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery")); this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), enumToString(vatClientQueryServer));
} }
void CNetworkVatlib::sendAtcQuery(const CCallsign &callsign) void CNetworkVatlib::sendAtcQuery(const CCallsign &callsign)
@@ -686,7 +687,7 @@ namespace BlackCore
Vat_SendClientQuery(m_net.data(), vatClientQueryAtc, toFSD(callsign)); Vat_SendClientQuery(m_net.data(), vatClientQueryAtc, toFSD(callsign));
// statistics // statistics
this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), vatClientQueryAtc); this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), enumToString(vatClientQueryAtc));
} }
void CNetworkVatlib::sendAtisQuery(const CCallsign &callsign) void CNetworkVatlib::sendAtisQuery(const CCallsign &callsign)
@@ -699,7 +700,7 @@ namespace BlackCore
Vat_SendClientQuery(m_net.data(), vatClientQueryAtis, toFSD(callsign)); Vat_SendClientQuery(m_net.data(), vatClientQueryAtis, toFSD(callsign));
// statistics // statistics
this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), vatClientQueryAtis); this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), enumToString(vatClientQueryAtis));
} }
void CNetworkVatlib::sendFlightPlan(const CFlightPlan &flightPlan) void CNetworkVatlib::sendFlightPlan(const CFlightPlan &flightPlan)
@@ -759,7 +760,7 @@ namespace BlackCore
Vat_SendClientQuery(m_net.data(), vatClientQueryFP, toFSD(callsign)); Vat_SendClientQuery(m_net.data(), vatClientQueryFP, toFSD(callsign));
// statistics // statistics
this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), vatClientQueryFP); this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), enumToString(vatClientQueryFP));
} }
void CNetworkVatlib::sendRealNameQuery(const CCallsign &callsign) void CNetworkVatlib::sendRealNameQuery(const CCallsign &callsign)
@@ -768,7 +769,7 @@ namespace BlackCore
Vat_SendClientQuery(m_net.data(), vatClientQueryName, toFSD(callsign)); Vat_SendClientQuery(m_net.data(), vatClientQueryName, toFSD(callsign));
// statistics // statistics
this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), vatClientQueryName); this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), enumToString(vatClientQueryName));
} }
void CNetworkVatlib::sendCapabilitiesQuery(const CCallsign &callsign) void CNetworkVatlib::sendCapabilitiesQuery(const CCallsign &callsign)
@@ -777,7 +778,7 @@ namespace BlackCore
Vat_SendClientQuery(m_net.data(), vatClientQueryCaps, toFSD(callsign)); Vat_SendClientQuery(m_net.data(), vatClientQueryCaps, toFSD(callsign));
// statistics // statistics
this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), vatClientQueryCaps); this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), enumToString(vatClientQueryCaps));
} }
void CNetworkVatlib::replyToFrequencyQuery(const CCallsign &callsign) // private void CNetworkVatlib::replyToFrequencyQuery(const CCallsign &callsign) // private
@@ -786,7 +787,7 @@ namespace BlackCore
Vat_SendClientQueryResponse(m_net.data(), vatClientQueryFreq, toFSD(callsign), toFSD(response)(), response.size()); Vat_SendClientQueryResponse(m_net.data(), vatClientQueryFreq, toFSD(callsign), toFSD(response)(), response.size());
// statistics // statistics
this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQueryResponse"), vatClientQueryFreq); this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQueryResponse"), enumToString(vatClientQueryFreq));
} }
void CNetworkVatlib::replyToNameQuery(const CCallsign &callsign) // private void CNetworkVatlib::replyToNameQuery(const CCallsign &callsign) // private
@@ -795,7 +796,7 @@ namespace BlackCore
Vat_SendClientQueryResponse(m_net.data(), vatClientQueryName, toFSD(callsign), toFSD(response)(), response.size()); Vat_SendClientQueryResponse(m_net.data(), vatClientQueryName, toFSD(callsign), toFSD(response)(), response.size());
// statistics // statistics
this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQueryResponse"), vatClientQueryName); this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQueryResponse"), enumToString(vatClientQueryName));
} }
void CNetworkVatlib::replyToConfigQuery(const CCallsign &callsign) void CNetworkVatlib::replyToConfigQuery(const CCallsign &callsign)
@@ -1476,9 +1477,31 @@ namespace BlackCore
return r.remove(':'); return r.remove(':');
} }
const QString &CNetworkVatlib::enumToString(VatClientQueryType type)
{
switch (type)
{
case vatClientQueryFP: { static const QString fp("vatClientQueryFP"); return fp; }
case vatClientQueryFreq: { static const QString fr("vatClientQueryFreq"); return fr; }
case vatClientQueryInfo: { static const QString in("vatClientQueryInfo"); return in; }
case vatClientQueryAtis: { static const QString at("vatClientQueryAtis"); return at; }
case vatClientQueryServer: { static const QString se("vatClientQueryServer"); return se; }
case vatClientQueryName: { static const QString na("vatClientQueryName"); return na; }
case vatClientQueryAtc: { static const QString ac("vatClientQueryAtc"); return ac; }
case vatClientQueryCaps: { static const QString ca("vatClientQueryCaps"); return ca; }
case vatClientQueryIP: { static const QString ip("vatClientQueryIP"); return ip; }
}
static const QString unknown = "????";
return unknown;
}
void CNetworkVatlib::onInfoQueryRequestReceived(VatFsdClient *, const char *callsignString, VatClientQueryType type, const char *, void *cbvar) void CNetworkVatlib::onInfoQueryRequestReceived(VatFsdClient *, const char *callsignString, VatClientQueryType type, const char *, void *cbvar)
{ {
QPointer<CNetworkVatlib> self(cbvar_cast(cbvar)); QPointer<CNetworkVatlib> self(cbvar_cast(cbvar));
// statistics
self->increaseStatisticsValue(__func__, enumToString(type));
const CCallsign callsign(self->fromFSD(callsignString)); const CCallsign callsign(self->fromFSD(callsignString));
const bool valid = !callsign.isEmpty(); const bool valid = !callsign.isEmpty();
BLACK_AUDIT_X(valid, Q_FUNC_INFO, "No callsign"); BLACK_AUDIT_X(valid, Q_FUNC_INFO, "No callsign");
@@ -1500,6 +1523,10 @@ namespace BlackCore
void CNetworkVatlib::onInfoQueryReplyReceived(VatFsdClient *, const char *callsign, VatClientQueryType type, const char *data, const char *data2, void *cbvar) void CNetworkVatlib::onInfoQueryReplyReceived(VatFsdClient *, const char *callsign, VatClientQueryType type, const char *data, const char *data2, void *cbvar)
{ {
auto *self = cbvar_cast(cbvar); auto *self = cbvar_cast(cbvar);
// statistics
self->increaseStatisticsValue(__func__, enumToString(type));
switch (type) switch (type)
{ {
case vatClientQueryFreq: emit self->frequencyReplyReceived(self->fromFSD(callsign), CFrequency(self->fromFSD(data).toDouble(), CFrequencyUnit::MHz())); break; case vatClientQueryFreq: emit self->frequencyReplyReceived(self->fromFSD(callsign), CFrequency(self->fromFSD(data).toDouble(), CFrequencyUnit::MHz())); break;
@@ -1519,12 +1546,20 @@ namespace BlackCore
if (capabilityFlags & vatCapsAircraftInfo) { caps |= CClient::FsdWithIcaoCodes; } if (capabilityFlags & vatCapsAircraftInfo) { caps |= CClient::FsdWithIcaoCodes; }
if (capabilityFlags & vatCapsAircraftConfig) { caps |= CClient::FsdWithAircraftConfig; } if (capabilityFlags & vatCapsAircraftConfig) { caps |= CClient::FsdWithAircraftConfig; }
auto *self = cbvar_cast(cbvar); auto *self = cbvar_cast(cbvar);
// statistics
self->increaseStatisticsValue(__func__);
emit self->capabilitiesReplyReceived(self->fromFSD(callsign), static_cast<int>(caps)); emit self->capabilitiesReplyReceived(self->fromFSD(callsign), static_cast<int>(caps));
} }
void CNetworkVatlib::onAtisReplyReceived(VatFsdClient *, const char *callsign, const VatControllerAtis *atis, void *cbvar) void CNetworkVatlib::onAtisReplyReceived(VatFsdClient *, const char *callsign, const VatControllerAtis *atis, void *cbvar)
{ {
auto *self = cbvar_cast(cbvar); auto *self = cbvar_cast(cbvar);
// statistics
self->increaseStatisticsValue(__func__);
const CCallsign cs(self->fromFSD(callsign), CCallsign::Atc); const CCallsign cs(self->fromFSD(callsign), CCallsign::Atc);
emit self->atisVoiceRoomReplyReceived(cs, self->fromFSD(atis->voiceRoom)); emit self->atisVoiceRoomReplyReceived(cs, self->fromFSD(atis->voiceRoom));
emit self->atisLogoffTimeReplyReceived(cs, self->fromFSD(atis->zuluLogoff)); emit self->atisLogoffTimeReplyReceived(cs, self->fromFSD(atis->zuluLogoff));
@@ -1566,6 +1601,10 @@ namespace BlackCore
} }
auto *self = cbvar_cast(cbvar); auto *self = cbvar_cast(cbvar);
// statistics
self->increaseStatisticsValue(__func__);
QString cruiseAltString = self->fromFSD(fp->cruiseAltitude).trimmed(); QString cruiseAltString = self->fromFSD(fp->cruiseAltitude).trimmed();
if (!cruiseAltString.isEmpty() && is09OnlyString(cruiseAltString)) if (!cruiseAltString.isEmpty() && is09OnlyString(cruiseAltString))
{ {
@@ -1599,8 +1638,8 @@ namespace BlackCore
CAltitude cruiseAlt; CAltitude cruiseAlt;
cruiseAlt.parseFromString(cruiseAltString, CPqString::SeparatorBestGuess); cruiseAlt.parseFromString(cruiseAltString, CPqString::SeparatorBestGuess);
const QString depTimePlanned = QString("0000").append(QString::number(fp->departTime)).right(4); const QString depTimePlanned = QStringLiteral("0000").append(QString::number(fp->departTime)).right(4);
const QString depTimeActual = QString("0000").append(QString::number(fp->departTimeActual)).right(4); const QString depTimeActual = QStringLiteral("0000").append(QString::number(fp->departTimeActual)).right(4);
const CCallsign callsign(self->fromFSD(callsignChar), CCallsign::Aircraft); const CCallsign callsign(self->fromFSD(callsignChar), CCallsign::Aircraft);
const CFlightPlan flightPlan( const CFlightPlan flightPlan(
@@ -1659,6 +1698,10 @@ namespace BlackCore
void CNetworkVatlib::onPilotInfoRequestReceived(VatFsdClient *, const char *callsignChar, void *cbvar) void CNetworkVatlib::onPilotInfoRequestReceived(VatFsdClient *, const char *callsignChar, void *cbvar)
{ {
QPointer<CNetworkVatlib> self(cbvar_cast(cbvar)); QPointer<CNetworkVatlib> self(cbvar_cast(cbvar));
// statistics
self->increaseStatisticsValue(__func__);
const CCallsign callsign(self->fromFSD(callsignChar)); const CCallsign callsign(self->fromFSD(callsignChar));
QTimer::singleShot(0, self, [ = ]() { if (self) { self->sendAircraftInfo(callsign); }}); QTimer::singleShot(0, self, [ = ]() { if (self) { self->sendAircraftInfo(callsign); }});
} }
@@ -1666,6 +1709,10 @@ namespace BlackCore
void CNetworkVatlib::onPilotInfoReceived(VatFsdClient *, const char *callsignChar, const VatAircraftInfo *aircraftInfo, void *cbvar) void CNetworkVatlib::onPilotInfoReceived(VatFsdClient *, const char *callsignChar, const VatAircraftInfo *aircraftInfo, void *cbvar)
{ {
auto *self = cbvar_cast(cbvar); auto *self = cbvar_cast(cbvar);
// statistics
self->increaseStatisticsValue(__func__);
const CCallsign callsign(self->fromFSD(callsignChar), CCallsign::Aircraft); const CCallsign callsign(self->fromFSD(callsignChar), CCallsign::Aircraft);
emit self->icaoCodesReplyReceived( emit self->icaoCodesReplyReceived(
callsign, callsign,

View File

@@ -264,6 +264,9 @@ namespace BlackCore
//! Remove colon //! Remove colon
static QString removeColon(const QString &candidate); static QString removeColon(const QString &candidate);
//! Enum as type
static const QString &enumToString(VatClientQueryType type);
//! Deletion policy for QScopedPointer //! Deletion policy for QScopedPointer
struct VatFsdClientDeleter struct VatFsdClientDeleter
{ {