Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8cfbf76ef7 | |||
| 971dad786b |
+25
-4
@@ -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
@@ -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);
|
||||
|
||||
@@ -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+ © 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}}";
|
||||
|
||||
@@ -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
@@ -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">
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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; }
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user