mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-30 11:55:35 +08:00
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:
committed by
Mat Sutcliffe
parent
419b837b65
commit
a5a6a111e1
@@ -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<qint64, QString>(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<std::pair<int, QString>> 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
|
||||
|
||||
@@ -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 <QString, int> m_callStatistics;
|
||||
bool m_statistics = false;
|
||||
QMap <QString, int> m_callStatistics;
|
||||
QVector <QPair<qint64, QString>> m_callByTime;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
||||
@@ -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<CNetworkVatlib> 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<int>(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<CNetworkVatlib> 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,
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user