diff --git a/src/webui/btjson.cpp b/src/webui/btjson.cpp index 0d2218c1b..6f1c2edc4 100644 --- a/src/webui/btjson.cpp +++ b/src/webui/btjson.cpp @@ -34,6 +34,7 @@ #include #include +#include "base/bittorrent/cachestatus.h" #include "base/bittorrent/session.h" #include "base/bittorrent/sessionstatus.h" #include "base/bittorrent/peerinfo.h" @@ -45,6 +46,7 @@ #include "base/torrentfilter.h" #include "base/utils/fs.h" #include "base/utils/misc.h" +#include "base/utils/string.h" #include "jsonutils.h" #define CACHED_VARIABLE(VARTYPE, VAR, DUR) \ @@ -186,6 +188,20 @@ static const char KEY_TRANSFER_UPRATELIMIT[] = "up_rate_limit"; static const char KEY_TRANSFER_DHT_NODES[] = "dht_nodes"; static const char KEY_TRANSFER_CONNECTION_STATUS[] = "connection_status"; +// Statistics keys +static const char KEY_TRANSFER_ALLTIME_DL[] = "alltime_dl"; +static const char KEY_TRANSFER_ALLTIME_UL[] = "alltime_ul"; +static const char KEY_TRANSFER_TOTAL_WASTE_SESSION[] = "total_wasted_session"; +static const char KEY_TRANSFER_GLOBAL_RATIO[] = "global_ratio"; +static const char KEY_TRANSFER_TOTAL_PEER_CONNECTIONS[] = "total_peer_connections"; +static const char KEY_TRANSFER_READ_CACHE_HITS[] = "read_cache_hits"; +static const char KEY_TRANSFER_TOTAL_BUFFERS_SIZE[] = "total_buffers_size"; +static const char KEY_TRANSFER_WRITE_CACHE_OVERLOAD[] = "write_cache_overload"; +static const char KEY_TRANSFER_READ_CACHE_OVERLOAD[] = "read_cache_overload"; +static const char KEY_TRANSFER_QUEUED_IO_JOBS[] = "queued_io_jobs"; +static const char KEY_TRANSFER_AVERAGE_TIME_QUEUE[] = "average_time_queue"; +static const char KEY_TRANSFER_TOTAL_QUEUED_SIZE[] = "total_queued_size"; + // Sync main data keys static const char KEY_SYNC_MAINDATA_QUEUEING[] = "queueing"; static const char KEY_SYNC_MAINDATA_USE_ALT_SPEED_LIMITS[] = "use_alt_speed_limits"; @@ -661,12 +677,37 @@ QVariantMap getTranserInfoMap() { QVariantMap map; BitTorrent::SessionStatus sessionStatus = BitTorrent::Session::instance()->status(); + BitTorrent::CacheStatus cacheStatus = BitTorrent::Session::instance()->cacheStatus(); map[KEY_TRANSFER_DLSPEED] = sessionStatus.payloadDownloadRate(); map[KEY_TRANSFER_DLDATA] = sessionStatus.totalPayloadDownload(); map[KEY_TRANSFER_UPSPEED] = sessionStatus.payloadUploadRate(); map[KEY_TRANSFER_UPDATA] = sessionStatus.totalPayloadUpload(); map[KEY_TRANSFER_DLRATELIMIT] = BitTorrent::Session::instance()->downloadSpeedLimit(); map[KEY_TRANSFER_UPRATELIMIT] = BitTorrent::Session::instance()->uploadSpeedLimit(); + + quint64 atd = BitTorrent::Session::instance()->getAlltimeDL(); + quint64 atu = BitTorrent::Session::instance()->getAlltimeUL(); + map[KEY_TRANSFER_ALLTIME_DL] = atd; + map[KEY_TRANSFER_ALLTIME_UL] = atu; + map[KEY_TRANSFER_TOTAL_WASTE_SESSION] = sessionStatus.totalWasted(); + map[KEY_TRANSFER_GLOBAL_RATIO] = ( atd > 0 && atu > 0 ) ? Utils::String::fromDouble((qreal)atu / (qreal)atd, 2) : "-"; + map[KEY_TRANSFER_TOTAL_PEER_CONNECTIONS] = sessionStatus.peersCount(); + + qreal readRatio = cacheStatus.readRatio(); + map[KEY_TRANSFER_READ_CACHE_HITS] = (readRatio >= 0) ? Utils::String::fromDouble(100 * readRatio, 2) : "-"; + map[KEY_TRANSFER_TOTAL_BUFFERS_SIZE] = cacheStatus.totalUsedBuffers() * 16 * 1024; + + // num_peers is not reliable (adds up peers, which didn't even overcome tcp handshake) + quint32 peers = 0; + foreach (BitTorrent::TorrentHandle *const torrent, BitTorrent::Session::instance()->torrents()) + peers += torrent->peersCount(); + map[KEY_TRANSFER_WRITE_CACHE_OVERLOAD] = ((sessionStatus.diskWriteQueue() > 0) && (peers > 0)) ? Utils::String::fromDouble((100. * sessionStatus.diskWriteQueue()) / peers, 2) : "0"; + map[KEY_TRANSFER_READ_CACHE_OVERLOAD] = ((sessionStatus.diskReadQueue() > 0) && (peers > 0)) ? Utils::String::fromDouble((100. * sessionStatus.diskReadQueue()) / peers, 2) : "0"; + + map[KEY_TRANSFER_QUEUED_IO_JOBS] = cacheStatus.jobQueueLength(); + map[KEY_TRANSFER_AVERAGE_TIME_QUEUE] = cacheStatus.averageJobTime(); + map[KEY_TRANSFER_TOTAL_QUEUED_SIZE] = cacheStatus.queuedBytes(); + map[KEY_TRANSFER_DHT_NODES] = sessionStatus.dhtNodes(); if (!BitTorrent::Session::instance()->isListening()) map[KEY_TRANSFER_CONNECTION_STATUS] = "disconnected"; diff --git a/src/webui/webui.qrc b/src/webui/webui.qrc index 011bb5d72..e7395c4cd 100644 --- a/src/webui/webui.qrc +++ b/src/webui/webui.qrc @@ -35,6 +35,7 @@ www/public/scripts/prop-trackers.js www/public/scripts/prop-webseeds.js www/public/scripts/prop-files.js + www/public/statistics.html www/public/transferlist.html www/public/upload.html www/public/uploadlimit.html diff --git a/src/webui/www/private/index.html b/src/webui/www/private/index.html index 4ed47a2c6..6c84891b0 100644 --- a/src/webui/www/private/index.html +++ b/src/webui/www/private/index.html @@ -63,6 +63,7 @@
  • diff --git a/src/webui/www/public/scripts/client.js b/src/webui/www/public/scripts/client.js index e1349326e..69ef2270b 100644 --- a/src/webui/www/public/scripts/client.js +++ b/src/webui/www/public/scripts/client.js @@ -367,6 +367,23 @@ window.addEvent('load', function () { }else document.title = "qBittorrent ${VERSION} QBT_TR(Web UI)QBT_TR"; $('DHTNodes').set('html', 'QBT_TR(DHT: %1 nodes)QBT_TR'.replace("%1", serverState.dht_nodes)); + + + if (document.getElementById("statisticspage")) { + $('AlltimeDL').set('html', 'Alltime download: %1'.replace("%1", friendlyUnit(serverState.alltime_dl, false))); + $('AlltimeUL').set('html', 'Alltime upload: %1'.replace("%1", friendlyUnit(serverState.alltime_ul, false))); + $('TotalWastedSession').set('html', 'Total wasted (this session): %1'.replace("%1", friendlyUnit(serverState.total_wasted_session, false))); + $('GlobalRatio').set('html', 'Global ratio: %1'.replace("%1", serverState.global_ratio )); + $('TotalPeerConnections').set('html', 'Total peer connections: %1'.replace("%1", serverState.total_peer_connections )); + $('ReadCacheHits').set('html', 'Read cache hits: %1'.replace("%1", serverState.read_cache_hits )); + $('TotalBuffersSize').set('html', 'Total buffers size: %1'.replace("%1", friendlyUnit(serverState.total_buffers_size, false))); + $('WriteCacheOverload').set('html', 'Write cache overload: %1'.replace("%1", serverState.write_cache_overload )); + $('ReadCacheOverload').set('html', 'Read cache overload: %1'.replace("%1", serverState.read_cache_overload )); + $('QueuedIOJobs').set('html', 'Queued I/O jobs: %1'.replace("%1", serverState.queued_io_jobs )); + $('AverageTimeInQueue').set('html', 'Average time in queue: %1'.replace("%1", serverState.average_time_queue )); + $('TotalQueuedSize').set('html', 'Total queued size: %1'.replace("%1", friendlyUnit(serverState.total_queued_size, false) )); + } + if (serverState.connection_status == "connected") $('connectionStatus').src = 'images/skin/connected.png'; else if (serverState.connection_status == "firewalled") @@ -451,6 +468,8 @@ window.addEvent('load', function () { processServerState(); }); + $('StatisticsLink').addEvent('click', StatisticsLinkFN); + new MochaUI.Panel({ id : 'transferList', title : 'Panel', diff --git a/src/webui/www/public/scripts/mocha-init.js b/src/webui/www/public/scripts/mocha-init.js index c5e98f96b..dc3c722e4 100644 --- a/src/webui/www/public/scripts/mocha-init.js +++ b/src/webui/www/public/scripts/mocha-init.js @@ -212,6 +212,21 @@ initializeWindows = function() { }); } + StatisticsLinkFN = function() { + new MochaUI.Window({ + id: 'statisticspage', + title: 'QBT_TR(Statistics)QBT_TR', + loadMethod: 'xhr', + contentURL: 'statistics.html', + scrollbars: false, + resizable: false, + maximizable: false, + width: 275, + height: 370, + padding: 10 + }); + } + downloadLimitFN = function() { var h = torrentsTable.selectedRowsIds(); if (h.length) { diff --git a/src/webui/www/public/statistics.html b/src/webui/www/public/statistics.html new file mode 100644 index 000000000..32248bc36 --- /dev/null +++ b/src/webui/www/public/statistics.html @@ -0,0 +1,47 @@ +

    User Statistics

    + + + + + + + + + + + + + + + + +
    + +

    Cache Statistics

    + + + + + + + +
    + +

    Performance Statistics

    + + + + + + + + + + + + + + + + +