From a5a6a111e19c4d28dcd158e5bef9f3b1b52c6593 Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Sat, 6 Jul 2019 00:20:24 +0200 Subject: [PATCH] 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 --- src/blackcore/network.cpp | 52 ++++++++++++++++-- src/blackcore/network.h | 13 +++-- src/blackcore/vatsim/networkvatlib.cpp | 73 +++++++++++++++++++++----- src/blackcore/vatsim/networkvatlib.h | 3 ++ 4 files changed, 121 insertions(+), 20 deletions(-) diff --git a/src/blackcore/network.cpp b/src/blackcore/network.cpp index 3beddbe40..251427cbb 100644 --- a/src/blackcore/network.cpp +++ b/src/blackcore/network.cpp @@ -7,6 +7,8 @@ */ #include "network.h" +#include "blackmisc/fileutils.h" +#include "blackmisc/directoryutils.h" #include "blackmisc/logmessage.h" #include "blackmisc/range.h" #include "blackconfig/buildconfig.h" @@ -33,11 +35,19 @@ namespace BlackCore } } + INetwork::~INetwork() + { } + int INetwork::increaseStatisticsValue(const QString &identifier, const QString &appendix) { 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++; + + constexpr int MaxTimeValues = 50; + m_callByTime.push_front(QPair(QDateTime::currentMSecsSinceEpoch(), i)); + if (m_callByTime.size() > MaxTimeValues) { m_callByTime.removeLast(); } return v; } @@ -46,17 +56,23 @@ namespace BlackCore return this->increaseStatisticsValue(identifier, QString::number(value)); } + void INetwork::clearStatistics() + { + m_callStatistics.clear(); + m_callByTime.clear(); + } + QString INetwork::getNetworkStatisticsAsText(bool reset, const QString &separator) { QVector> transformed; + if (m_callStatistics.isEmpty()) { return QString(); } + for (const auto pair : makePairsRange(as_const(m_callStatistics))) { // key is pair.first, value is pair.second transformed.push_back({ pair.second, pair.first }); } - if (reset) { this->clearStatistics(); } - // sorted by value std::sort(transformed.begin(), transformed.end(), std::greater<>()); QString stats; @@ -66,7 +82,37 @@ namespace BlackCore (stats.isEmpty() ? QString() : separator) % 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; } + 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 diff --git a/src/blackcore/network.h b/src/blackcore/network.h index afcded0ec..acd3bec7d 100644 --- a/src/blackcore/network.h +++ b/src/blackcore/network.h @@ -80,7 +80,7 @@ namespace BlackCore public: //! Destructor - virtual ~INetwork() {} + virtual ~INetwork(); //! Underlying library info. virtual const QString &getLibraryInfo(bool detailed) const = 0; @@ -117,7 +117,7 @@ namespace BlackCore //! @} //! Clear the statistics - void clearStatistics() { m_callStatistics.clear(); } + void clearStatistics(); //! Text statistics QString getNetworkStatisticsAsText(bool reset, const QString &separator = "\n"); @@ -599,9 +599,14 @@ namespace BlackCore //! @} + protected: + //! Save the statistics + bool saveNetworkStatistics(const QString &server); + private: - bool m_statistics = false; - QMap m_callStatistics; + bool m_statistics = false; + QMap m_callStatistics; + QVector > m_callByTime; }; } // namespace diff --git a/src/blackcore/vatsim/networkvatlib.cpp b/src/blackcore/vatsim/networkvatlib.cpp index 803c1b1bf..00a4a7606 100644 --- a/src/blackcore/vatsim/networkvatlib.cpp +++ b/src/blackcore/vatsim/networkvatlib.cpp @@ -305,6 +305,7 @@ namespace BlackCore this->clearState(); this->setLastEcosystem(m_server.getEcosystem()); this->setCurrentEcosystem(CEcosystem::NoSystem); + this->saveNetworkStatistics(m_server.getName()); } emit this->connectionStatusChanged(convertConnectionStatus(status), convertConnectionStatus(m_status)); @@ -627,7 +628,7 @@ namespace BlackCore Vat_SendClientQuery(m_net.data(), vatClientQueryIP, nullptr); // statistics - this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery")); + this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), enumToString(vatClientQueryIP)); } void CNetworkVatlib::sendFrequencyQuery(const CCallsign &callsign) @@ -636,7 +637,7 @@ namespace BlackCore Vat_SendClientQuery(m_net.data(), vatClientQueryFreq, toFSD(callsign)); // statistics - this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), vatClientQueryFreq); + this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), enumToString(vatClientQueryFreq)); } void CNetworkVatlib::sendUserInfoQuery(const CCallsign &callsign) @@ -645,7 +646,7 @@ namespace BlackCore Vat_SendClientQuery(m_net.data(), vatClientQueryInfo, toFSD(callsign)); // statistics - this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), vatClientQueryInfo); + this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), enumToString(vatClientQueryInfo)); } void CNetworkVatlib::setInterimPositionReceivers(const CCallsignSet &receivers) @@ -677,7 +678,7 @@ namespace BlackCore Vat_SendClientQuery(m_net.data(), vatClientQueryServer, toFSD(callsign)); // statistics - this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery")); + this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), enumToString(vatClientQueryServer)); } void CNetworkVatlib::sendAtcQuery(const CCallsign &callsign) @@ -686,7 +687,7 @@ namespace BlackCore Vat_SendClientQuery(m_net.data(), vatClientQueryAtc, toFSD(callsign)); // statistics - this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), vatClientQueryAtc); + this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), enumToString(vatClientQueryAtc)); } void CNetworkVatlib::sendAtisQuery(const CCallsign &callsign) @@ -699,7 +700,7 @@ namespace BlackCore Vat_SendClientQuery(m_net.data(), vatClientQueryAtis, toFSD(callsign)); // statistics - this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), vatClientQueryAtis); + this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), enumToString(vatClientQueryAtis)); } void CNetworkVatlib::sendFlightPlan(const CFlightPlan &flightPlan) @@ -759,7 +760,7 @@ namespace BlackCore Vat_SendClientQuery(m_net.data(), vatClientQueryFP, toFSD(callsign)); // statistics - this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), vatClientQueryFP); + this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), enumToString(vatClientQueryFP)); } void CNetworkVatlib::sendRealNameQuery(const CCallsign &callsign) @@ -768,7 +769,7 @@ namespace BlackCore Vat_SendClientQuery(m_net.data(), vatClientQueryName, toFSD(callsign)); // statistics - this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), vatClientQueryName); + this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), enumToString(vatClientQueryName)); } void CNetworkVatlib::sendCapabilitiesQuery(const CCallsign &callsign) @@ -777,7 +778,7 @@ namespace BlackCore Vat_SendClientQuery(m_net.data(), vatClientQueryCaps, toFSD(callsign)); // statistics - this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), vatClientQueryCaps); + this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQuery"), enumToString(vatClientQueryCaps)); } 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()); // statistics - this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQueryResponse"), vatClientQueryFreq); + this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQueryResponse"), enumToString(vatClientQueryFreq)); } 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()); // statistics - this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQueryResponse"), vatClientQueryName); + this->increaseStatisticsValue(QStringLiteral("Vat_SendClientQueryResponse"), enumToString(vatClientQueryName)); } void CNetworkVatlib::replyToConfigQuery(const CCallsign &callsign) @@ -1476,9 +1477,31 @@ namespace BlackCore 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) { QPointer self(cbvar_cast(cbvar)); + + // statistics + self->increaseStatisticsValue(__func__, enumToString(type)); + const CCallsign callsign(self->fromFSD(callsignString)); const bool valid = !callsign.isEmpty(); 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) { auto *self = cbvar_cast(cbvar); + + // statistics + self->increaseStatisticsValue(__func__, enumToString(type)); + switch (type) { 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 & vatCapsAircraftConfig) { caps |= CClient::FsdWithAircraftConfig; } auto *self = cbvar_cast(cbvar); + + // statistics + self->increaseStatisticsValue(__func__); + emit self->capabilitiesReplyReceived(self->fromFSD(callsign), static_cast(caps)); } void CNetworkVatlib::onAtisReplyReceived(VatFsdClient *, const char *callsign, const VatControllerAtis *atis, void *cbvar) { auto *self = cbvar_cast(cbvar); + + // statistics + self->increaseStatisticsValue(__func__); + const CCallsign cs(self->fromFSD(callsign), CCallsign::Atc); emit self->atisVoiceRoomReplyReceived(cs, self->fromFSD(atis->voiceRoom)); emit self->atisLogoffTimeReplyReceived(cs, self->fromFSD(atis->zuluLogoff)); @@ -1566,6 +1601,10 @@ namespace BlackCore } auto *self = cbvar_cast(cbvar); + + // statistics + self->increaseStatisticsValue(__func__); + QString cruiseAltString = self->fromFSD(fp->cruiseAltitude).trimmed(); if (!cruiseAltString.isEmpty() && is09OnlyString(cruiseAltString)) { @@ -1599,8 +1638,8 @@ namespace BlackCore CAltitude cruiseAlt; cruiseAlt.parseFromString(cruiseAltString, CPqString::SeparatorBestGuess); - const QString depTimePlanned = QString("0000").append(QString::number(fp->departTime)).right(4); - const QString depTimeActual = QString("0000").append(QString::number(fp->departTimeActual)).right(4); + const QString depTimePlanned = QStringLiteral("0000").append(QString::number(fp->departTime)).right(4); + const QString depTimeActual = QStringLiteral("0000").append(QString::number(fp->departTimeActual)).right(4); const CCallsign callsign(self->fromFSD(callsignChar), CCallsign::Aircraft); const CFlightPlan flightPlan( @@ -1659,6 +1698,10 @@ namespace BlackCore void CNetworkVatlib::onPilotInfoRequestReceived(VatFsdClient *, const char *callsignChar, void *cbvar) { QPointer self(cbvar_cast(cbvar)); + + // statistics + self->increaseStatisticsValue(__func__); + const CCallsign callsign(self->fromFSD(callsignChar)); 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) { auto *self = cbvar_cast(cbvar); + + // statistics + self->increaseStatisticsValue(__func__); + const CCallsign callsign(self->fromFSD(callsignChar), CCallsign::Aircraft); emit self->icaoCodesReplyReceived( callsign, diff --git a/src/blackcore/vatsim/networkvatlib.h b/src/blackcore/vatsim/networkvatlib.h index 9cb6df426..4032983fd 100644 --- a/src/blackcore/vatsim/networkvatlib.h +++ b/src/blackcore/vatsim/networkvatlib.h @@ -264,6 +264,9 @@ namespace BlackCore //! Remove colon static QString removeColon(const QString &candidate); + //! Enum as type + static const QString &enumToString(VatClientQueryType type); + //! Deletion policy for QScopedPointer struct VatFsdClientDeleter {