Files
pip/libs/main/io_utils/pidiagnostics.h
2026-03-12 14:46:57 +03:00

240 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! \~\file pidiagnostics.h
//! \~\ingroup IO-Utils
//! \~\brief
//! \~english Connection quality diagnostics
//! \~russian Диагностика качества связи
/*
PIP - Platform Independent Primitives
Speed and quality in/out diagnostics
Andrey Bychkov work.a.b@yandex.ru, Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIDIAGNOSTICS_H
#define PIDIAGNOSTICS_H
#include "piqueue.h"
#include "pitimer.h"
//! \~\ingroup IO-Utils
//! \brief
//! \~english Connection diagnostics for packet frequency, throughput and receive quality
//! \~russian Диагностика соединения для частоты пакетов, пропускной способности и качества приема
//! \details
//! \~english This class provides connection quality diagnostics based on packet reception statistics
//! \~russian Класс обеспечивает диагностику качества связи на основе статистики приема пакетов
class PIP_EXPORT PIDiagnostics: public PITimer {
PIOBJECT_SUBCLASS(PIDiagnostics, PITimer);
friend class PIConnection;
public:
NO_COPY_CLASS(PIDiagnostics);
//! \~english Constructs diagnostics and optionally starts periodic evaluation immediately.
//! \~russian Создает диагностику и при необходимости сразу запускает периодическую оценку.
PIDiagnostics(bool start_ = true);
//! \~english Stops diagnostics updates.
//! \~russian Останавливает обновление диагностики.
virtual ~PIDiagnostics();
//! \~english Receive quality estimated from recent packet history.
//! \~russian Качество приема, оцениваемое по недавней истории пакетов.
enum Quality {
Unknown = 1 /** \~english No receive history yet \~russian История приема еще отсутствует */,
Failure = 2 /** \~english No correct packets in the recent window \~russian В недавнем окне нет корректных пакетов */,
Bad = 3 /** \~english Correct packets are at most 20 percent \~russian Корректных пакетов не более 20 процентов */,
Average =
4 /** \~english Correct packets are above 20 and up to 80 percent \~russian Корректных пакетов больше 20 и до 80 процентов */
,
Good = 5 /** \~english Correct packets are above 80 percent \~russian Корректных пакетов больше 80 процентов */
};
//! \~english Snapshot of current counters and derived statistics.
//! \~russian Снимок текущих счетчиков и производных статистик.
struct PIP_EXPORT State {
//! \~english Constructs zeroed state with formatted speed strings.
//! \~russian Создает обнуленное состояние с отформатированными строками скоростей.
State();
//! \~english Latest receive frequency for the current timer interval.
//! \~russian Последняя частота приема для текущего интервала таймера.
float immediate_freq = 0.f;
//! \~english Averaged receive frequency over the disconnect window.
//! \~russian Усредненная частота приема по окну отключения.
float integral_freq = 0.f;
//! \~english Number of correct received packets per second.
//! \~russian Число корректно принятых пакетов в секунду.
ullong received_packets_per_sec = 0ull;
//! \~english Total number of correct received packets.
//! \~russian Общее число корректно принятых пакетов.
ullong received_packets = 0ull;
//! \~english Total number of incorrect received packets.
//! \~russian Общее число некорректно принятых пакетов.
ullong received_packets_wrong = 0ull;
//! \~english Number of received bytes per second.
//! \~russian Число принятых байтов в секунду.
ullong received_bytes_per_sec = 0ull;
//! \~english Total number of correctly received bytes.
//! \~russian Общее число корректно принятых байтов.
ullong received_bytes = 0ull;
//! \~english Total number of bytes from incorrect packets.
//! \~russian Общее число байтов из некорректных пакетов.
ullong received_bytes_wrong = 0ull;
//! \~english Number of sent packets per second.
//! \~russian Число отправленных пакетов в секунду.
ullong sended_packets_per_sec = 0ull;
//! \~english Total number of sent packets.
//! \~russian Общее число отправленных пакетов.
ullong sended_packets = 0ull;
//! \~english Number of sent bytes per second.
//! \~russian Число отправленных байтов в секунду.
ullong sended_bytes_per_sec = 0ull;
//! \~english Total number of sent bytes.
//! \~russian Общее число отправленных байтов.
ullong sended_bytes = 0ull;
//! \~english Human-readable receive speed string.
//! \~russian Строка скорости приема в человекочитаемом виде.
PIString receive_speed;
//! \~english Human-readable send speed string.
//! \~russian Строка скорости отправки в человекочитаемом виде.
PIString send_speed;
//! \~english Current receive quality category.
//! \~russian Текущая категория качества приема.
PIDiagnostics::Quality quality = PIDiagnostics::Unknown;
};
//! \~english Returns a thread-safe snapshot of current diagnostics state.
//! \~russian Возвращает потокобезопасный снимок текущего состояния диагностики.
PIDiagnostics::State state() const;
//! \~english Returns the disconnect timeout and averaging window.
//! \~russian Возвращает таймаут отключения и окно усреднения.
PISystemTime disconnectTimeout() const { return disconn_; }
//! \~english Sets the disconnect timeout in seconds.
//! \~russian Устанавливает таймаут отключения в секундах.
void setDisconnectTimeout(float s) DEPRECATEDM("use setDisconnectTimeout(PISystemTime)") {
setDisconnectTimeout(PISystemTime::fromSeconds(s));
}
//! \~english Sets the disconnect timeout and averaging window.
//! \~russian Устанавливает таймаут отключения и окно усреднения.
void setDisconnectTimeout(PISystemTime tm) { setProperty("disconnectTimeout", tm); }
//! \~english Returns current receive quality.
//! \~russian Возвращает текущее качество приема.
PIDiagnostics::Quality quality() const;
//! \~english Returns formatted receive throughput string.
//! \~russian Возвращает строку отформатированной скорости приема.
PIString receiveSpeed() const;
//! \~english Returns formatted send throughput string.
//! \~russian Возвращает строку отформатированной скорости отправки.
PIString sendSpeed() const;
//! \handlers
//! \{
//! \fn void start()
//! \~english Starts periodic diagnostics evaluation with the default interval.
//! \~russian Запускает периодическую оценку диагностики с интервалом по умолчанию.
EVENT_HANDLER0(void, start);
//! \fn void start(PISystemTime interval)
//! \~english Starts periodic diagnostics evaluation with interval "interval".
//! \~russian Запускает периодическую оценку диагностики с интервалом "interval".
EVENT_HANDLER1(void, start, PISystemTime, interval);
//! \fn void reset()
//! \~english Resets counters, rolling history and derived statistics.
//! \~russian Сбрасывает счетчики, скользящую историю и производные статистики.
EVENT_HANDLER0(void, reset);
//! \fn void received(int size, bool correct = true)
//! \~english Notifies diagnostics about one received packet of size "size".
//! \~russian Уведомляет диагностику об одном принятом пакете размером "size".
EVENT_HANDLER1(void, received, int, size) { received(size, true); }
EVENT_HANDLER2(void, received, int, size, bool, correct);
//! \fn void sended(int size)
//! \~english Notifies diagnostics about one sent packet of size "size".
//! \~russian Уведомляет диагностику об одном отправленном пакете размером "size".
EVENT_HANDLER1(void, sended, int, size);
//! \}
//! \events
//! \{
//! \fn void qualityChanged(PIDiagnostics::Quality new_quality, PIDiagnostics::Quality old_quality)
//! \~english Emitted when receive quality changes from "old_quality" to "new_quality".
//! \~russian Генерируется при изменении качества приема с "old_quality" на "new_quality".
EVENT2(qualityChanged, PIDiagnostics::Quality, new_quality, PIDiagnostics::Quality, old_quality);
//! \}
private:
struct PIP_EXPORT Entry {
ullong bytes_ok = 0;
ullong bytes_fail = 0;
uint cnt_ok = 0;
uint cnt_fail = 0;
bool empty = true;
};
friend bool operator==(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s);
friend bool operator!=(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s);
friend bool operator<(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s);
void tick(int) override;
Entry calcHistory(PIQueue<Entry> & hist, int & cnt);
void propertyChanged(const char *) override;
void changeDisconnectTimeout(PISystemTime disct);
PIQueue<Entry> history_rec, history_send;
PISystemTime disconn_;
State cur_state;
mutable PIMutex mutex_state;
};
inline bool operator==(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s) {
return f.bytes_ok == s.bytes_ok && f.bytes_fail == s.bytes_fail && f.cnt_ok == s.cnt_ok && f.cnt_fail == s.cnt_fail &&
f.empty == s.empty;
}
inline bool operator!=(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s) {
return !(f == s);
}
inline bool operator<(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s) {
return f.bytes_ok < s.bytes_ok;
}
#endif // PIDIAGNOSTICS_H