2 Commits

Author SHA1 Message Date
acetone 8cfbf76ef7 v0.0.2 2023-02-10 11:26:39 +03:00
acetone 971dad786b total history 2023-02-10 10:55:04 +03:00
12 changed files with 95 additions and 21 deletions
+25 -4
View File
@@ -78,11 +78,32 @@ void DBManager::initAtStart()
query.exec ("VACUUM");
}
TopDestinationList DBManager::totalTop() const
DestinationList DBManager::allHistory() const
{
QSqlQuery query(m_db);
TopDestinationList result;
DestinationList result;
if (not query.exec("SELECT * FROM total_history ORDER BY request_counter DESC"))
{
qCritical() << "Db query failed:" << query.lastError().text();
}
else
{
while (query.next())
{
result.push_back( {query.value(0).toString(), query.value(1).toULongLong()} );
}
}
return result;
}
DestinationList DBManager::totalTop() const
{
QSqlQuery query(m_db);
DestinationList result;
if (not query.exec("SELECT * FROM total_history ORDER BY request_counter DESC LIMIT " + QString::number(g::p::LAST_AND_TOP_LIST_SIZE)))
{
@@ -99,11 +120,11 @@ TopDestinationList DBManager::totalTop() const
return result;
}
TopDestinationList DBManager::dailyTop() const
DestinationList DBManager::dailyTop() const
{
QSqlQuery query(m_db);
TopDestinationList result;
DestinationList result;
if (not query.exec("SELECT * FROM daily_history ORDER BY request_counter DESC LIMIT " + QString::number(g::p::LAST_AND_TOP_LIST_SIZE)))
{
+3 -2
View File
@@ -43,8 +43,9 @@ public:
DBManager();
void initAtStart();
TopDestinationList totalTop() const;
TopDestinationList dailyTop() const;
DestinationList allHistory() const;
DestinationList totalTop() const;
DestinationList dailyTop() const;
quint64 totalTopCount(const QString& dest) const;
quint64 dailyTopCount(const QString& dest) const;
quint64 incrementTotalTopCount(const QString& dest);
+1 -1
View File
@@ -32,7 +32,7 @@ namespace g {
namespace c {
const QString SOFTWARE_NAME = "3proxy-eagle";
const QString SOFTWARE_VERSION = "0.0.1";
const QString COPYRIGHT = "GPLv3 (c) acetone, 2022";
const QString COPYRIGHT = "GPLv3+ &copy acetone, 2022-2023";
const qint64 DB_DAILY_TOP_TABLE_ACTUALIZE_MINIMAL_INTERVAL_MS = 300000; // 5 min
const qint64 CACHE_ACTUALIZE_TOP_LISTS_FROM_DB_MINIMAL_INTERVAL_MS = 5000; // 5 sec
const QString HA_PAGE_TITLE = "{{PAGE_TITLE}}";
+1 -1
View File
@@ -27,7 +27,7 @@ class QFile;
class ProxyInstanse;
class QThread;
using TopDestinationList = QList<QPair<QString, quint64>>;
using DestinationList = QList<QPair<QString, quint64>>;
namespace g /* for Global */ {
+1 -1
View File
@@ -99,7 +99,7 @@
</section>{{INFORMATION}}
<section class="proxyService__topDestinations topDestinations section">
<div class="section__title">
Top {{TOP_MEASURE}}
Top {{TOP_MEASURE}} <a href="/~stats.txt" target="_blank" style="color: gray">(all)</a>
</div>
<div class="topDestinations__block">
<div class="topDestinations__title">
+16
View File
@@ -82,6 +82,22 @@ void HttpDocument::setBody(const QByteArray &body)
m_body = body;
}
void HttpDocument::setBody(const QString &body, const QString &oldETag)
{
QString eTag = g::hash(body.toUtf8());
if (oldETag == eTag)
{
qDebug() << "Data cached by user (not file on disk) / Hash:" << oldETag;
setCode(Code::_304);
return;
}
setBody(body.toUtf8());
setHeader(CommonHeader::ETag, eTag);
}
void HttpDocument::setBody(const QJsonObject &body)
{
m_body = QJsonDocument(body).toJson(QJsonDocument::JsonFormat::Compact);
+1
View File
@@ -74,6 +74,7 @@ public:
void setBody(const QByteArray& body);
void setBody(const QJsonObject& body);
void setBody(QFile&& payload, const QString& eTag = QString());
void setBody(const QString& body, const QString& eTag);
void setBodySingleHTMLLabel(const QString& text, const QString& title = "Notice");
QByteArray body() const { return m_body; }
+7 -1
View File
@@ -18,6 +18,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "socketrunnable.h"
#include "statistics.h"
#include "g.h"
#include "webpage.h"
@@ -49,7 +50,12 @@ void SocketRunnable::get()
QString eTag = g::getValue(m_headers, "If-None-Match", g::GetValueType::HttpHeader);
if (urlPath() == "/main.css")
if (urlPath() == "/~stats.txt")
{
httpDocument().setBody(Statistics::statsTxt(), eTag);
httpDocument().setHeader(HttpDocument::CommonHeader::ContentType, HttpDocument::ContentType::TEXT);
}
else if (urlPath() == "/main.css")
{
httpDocument().setBody(QFile(":/html/main.css"), eTag);
}
+31 -4
View File
@@ -19,6 +19,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include "statistics.h"
#include "dbmanager.h"
#include "webpage.h"
#include "g.h"
#include <QRegularExpression>
@@ -36,8 +37,8 @@ std::atomic<quint64> Statistics::m_totalUpload {0};
std::atomic<quint64> Statistics::m_totalDownload {0};
QMutex Statistics::m_topDestinationsMtx;
TopDestinationList Statistics::m_dailyTopDestinations;
TopDestinationList Statistics::m_totalTopDestinations;
DestinationList Statistics::m_dailyTopDestinations;
DestinationList Statistics::m_totalTopDestinations;
bool Statistics::m_cacheUpdatedAfterLastReport = false;
qint64 Statistics::m_actualizeTopListsLastTimestamp = 0;
@@ -91,7 +92,7 @@ const QStringList Statistics::lastDestinations()
return m_lastDestinations;
}
const TopDestinationList Statistics::dailyTopDestinations()
const DestinationList Statistics::dailyTopDestinations()
{
if (not m_cacheUpdatedAfterLastReport)
{
@@ -101,7 +102,7 @@ const TopDestinationList Statistics::dailyTopDestinations()
return m_dailyTopDestinations;
}
const TopDestinationList Statistics::totalTopDestinations()
const DestinationList Statistics::totalTopDestinations()
{
QMutexLocker lock (&m_topDestinationsMtx);
return m_totalTopDestinations;
@@ -116,6 +117,32 @@ void Statistics::initTrafficCounters()
m_totalUpload = db.totalUploadTraffic();
}
QString Statistics::statsTxt()
{
static QMutex mtx;
if (not mtx.tryLock())
{
return "Service is busy, try again later.";
}
auto raw = DBManager().allHistory();
quint64 totalRequests = 0;
QString result;
for (const auto& record: raw)
{
result += WebPage::counterToHumanReadableString(record.second) + "\t" + record.first + "\n";
totalRequests += record.second;
}
result.push_front("Total destinations: " + WebPage::counterToHumanReadableString(raw.size()) + "\n"
"Total requests: " + WebPage::counterToHumanReadableString(totalRequests) + "\n\n");
mtx.unlock();
return result;
}
void Statistics::actualizeTopLists()
{
QMutexLocker lock (&m_topDestinationsMtx);
+6 -4
View File
@@ -40,8 +40,8 @@ public:
static const QStringList lastDestinations();
static const TopDestinationList dailyTopDestinations();
static const TopDestinationList totalTopDestinations();
static const DestinationList dailyTopDestinations();
static const DestinationList totalTopDestinations();
static void initTrafficCounters();
static quint64 dailyUpload() { return m_dailyUpload; }
@@ -49,6 +49,8 @@ public:
static quint64 dailyDownload() { return m_dailyDownload; }
static quint64 totalDownload() { return m_totalDownload; }
static QString statsTxt();
private:
static void actualizeTopLists();
static bool isIpAddress(const QString& dest);
@@ -65,7 +67,7 @@ private:
static std::atomic<quint64> m_totalDownload;
static QMutex m_topDestinationsMtx;
static TopDestinationList m_dailyTopDestinations;
static TopDestinationList m_totalTopDestinations;
static DestinationList m_dailyTopDestinations;
static DestinationList m_totalTopDestinations;
};
+2 -2
View File
@@ -192,10 +192,10 @@ quint64 WebPage::trafficBlock(QString &document, quint64 lastTrafficVolume)
document.replace(g::c::HA_DAILY_DOWNLOAD_MEASURE, dailyDownload.measure);
auto totalUpload = bytesToHumanReadableString( Statistics::totalUpload() );
document.replace(g::c::HA_TOTAL_UPLOAD, totalUpload.integer + " " + totalUpload.measure);
document.replace(g::c::HA_TOTAL_UPLOAD, totalUpload.integer + totalUpload.decimal + " " + totalUpload.measure);
auto totalDownload = bytesToHumanReadableString( Statistics::totalDownload() );
document.replace(g::c::HA_TOTAL_DOWNLOAD, totalDownload.integer + " " + totalDownload.measure);
document.replace(g::c::HA_TOTAL_DOWNLOAD, totalDownload.integer + totalDownload.decimal + " " + totalDownload.measure);
return currentVolume;
}
+1 -1
View File
@@ -29,6 +29,7 @@ class WebPage
public:
WebPage() = delete;
static QByteArray document(quint64 lastTrafficVolume, quint64* currentTrafficVolume = nullptr);
static QString counterToHumanReadableString(quint64 count);
private:
static void setTitle(QString& document);
@@ -45,7 +46,6 @@ private:
static QString topDestinationItem(const QString& destination, quint64 count);
static QString blockedDestinationItem(const QString& destination, const QStringList& addresses);
static HumanReadableValue bytesToHumanReadableString(quint64 bytes);
static QString counterToHumanReadableString(quint64 count);
static const QString m_lastDestinationItemAllowed;
static const QString m_lastDestinationItemBlocked;