loleaflet/admin.strings.js | 2 ++ loleaflet/dist/admin/admin.html | 14 +++++++++++--- loleaflet/dist/admin/dashboard.css | 2 +- loleaflet/src/admin/AdminSocketOverview.js | 10 ++++++++-- wsd/Admin.cpp | 23 ++++++++++++++++++----- wsd/Admin.hpp | 5 +++-- wsd/AdminModel.cpp | 12 ++++++++++++ wsd/AdminModel.hpp | 21 ++++++++++++++++++++- wsd/DocumentBroker.cpp | 24 +++++++++++++++++++++++- wsd/DocumentBroker.hpp | 1 + wsd/protocol.txt | 11 ++++++++--- 11 files changed, 107 insertions(+), 18 deletions(-)
New commits: commit eeaf436d5353cac3846e7cd69dc3a012eedf6cb0 Author: Michael Meeks <michael.me...@collabora.com> Date: Sat Jun 3 22:53:57 2017 +0100 Admin: show cumulative bandwidth sent / recv'd over all time. Change-Id: I3f9f398d1de19d54e0aa4c51bc44c597019dc839 diff --git a/loleaflet/admin.strings.js b/loleaflet/admin.strings.js index 5d21e7aa..a38f9a0e 100644 --- a/loleaflet/admin.strings.js +++ b/loleaflet/admin.strings.js @@ -15,6 +15,8 @@ l10nstrings.strUserName = _('Users Name'); l10nstrings.strDocumentsOpened = _('Documents opened'); l10nstrings.strDocumentNumber = _('Number of Documents'); l10nstrings.strMemoryConsumed = _('Memory consumed'); +l10nstrings.strSentBytes = _('Bytes sent'); +l10nstrings.strRecvBytes = _('Bytes received'); l10nstrings.strPid = _('PID'); l10nstrings.strDocument = _('Document'); l10nstrings.strNumberOfViews = _('Number of views'); diff --git a/loleaflet/dist/admin/admin.html b/loleaflet/dist/admin/admin.html index 72308e88..4bbc063f 100644 --- a/loleaflet/dist/admin/admin.html +++ b/loleaflet/dist/admin/admin.html @@ -65,18 +65,26 @@ <h1 class="page-header"><script>document.write(l10nstrings.strDashboard)</script></h1> <div class="row placeholders"> - <div class="col-xs-6 col-sm-3 placeholder"> + <div class="col-xs-6 col-sm-2 placeholder"> <div class="main-data" id="active_users_count">0</div> <h4><script>document.write(l10nstrings.strUsersOnline)</script></h4> </div> - <div class="col-xs-6 col-sm-3 placeholder"> + <div class="col-xs-6 col-sm-2 placeholder"> <div class="main-data" id="active_docs_count">0</div> <h4><script>document.write(l10nstrings.strDocumentsOpened)</script></h4> </div> - <div class="col-xs-6 col-sm-3 placeholder"> + <div class="col-xs-6 col-sm-2 placeholder"> <div class="main-data" id="total_mem">0</div> <h4><script>document.write(l10nstrings.strMemoryConsumed)</script></h4> </div> + <div class="col-xs-6 col-sm-2 placeholder"> + <div class="main-data" id="sent_bytes">0</div> + <h4><script>document.write(l10nstrings.strSentBytes)</script></h4> + </div> + <div class="col-xs-6 col-sm-2 placeholder"> + <div class="main-data" id="recv_bytes">0</div> + <h4><script>document.write(l10nstrings.strRecvBytes)</script></h4> + </div> </div> <div class="container"> <ul class="nav nav-tabs"> diff --git a/loleaflet/dist/admin/dashboard.css b/loleaflet/dist/admin/dashboard.css index 0535a2fd..d443ecfe 100644 --- a/loleaflet/dist/admin/dashboard.css +++ b/loleaflet/dist/admin/dashboard.css @@ -102,7 +102,7 @@ body { .placeholder .main-data { display: inline-block; border-radius: 50%; - font-size: 60px; + font-size: 45px; } /* diff --git a/loleaflet/src/admin/AdminSocketOverview.js b/loleaflet/src/admin/AdminSocketOverview.js index dfb92b64..a0726e60 100644 --- a/loleaflet/src/admin/AdminSocketOverview.js +++ b/loleaflet/src/admin/AdminSocketOverview.js @@ -16,6 +16,8 @@ var AdminSocketOverview = AdminSocketBase.extend({ this.socket.send('total_mem'); this.socket.send('active_docs_count'); this.socket.send('active_users_count'); + this.socket.send('sent_bytes'); + this.socket.send('recv_bytes'); }, onSocketOpen: function() { @@ -341,13 +343,17 @@ var AdminSocketOverview = AdminSocketBase.extend({ } else if (textMsg.startsWith('total_mem') || textMsg.startsWith('active_docs_count') || - textMsg.startsWith('active_users_count')) + textMsg.startsWith('active_users_count') || + textMsg.startsWith('sent_bytes') || + textMsg.startsWith('recv_bytes')) { textMsg = textMsg.split(' '); var sCommand = textMsg[0]; var nData = parseInt(textMsg[1]); - if (sCommand === 'total_mem') { + if (sCommand === 'total_mem' || + sCommand === 'sent_bytes' || + sCommand === 'recv_bytes') { nData = Util.humanizeMem(nData); } $(document.getElementById(sCommand)).text(nData); diff --git a/wsd/Admin.cpp b/wsd/Admin.cpp index fdea3f9a..1c15aa1d 100644 --- a/wsd/Admin.cpp +++ b/wsd/Admin.cpp @@ -140,10 +140,14 @@ void AdminSocketHandler::handleMessage(bool /* fin */, WSOpCode /* code */, } } else if (tokens[0] == "total_mem") - { - const auto totalMem = _admin->getTotalMemoryUsage(); - sendTextFrame("total_mem " + std::to_string(totalMem)); - } + sendTextFrame("total_mem " + std::to_string(_admin->getTotalMemoryUsage())); + + else if (tokens[0] == "sent_bytes") + sendTextFrame("sent_bytes " + std::to_string(model.getSentBytesTotal() / 1024)); + + else if (tokens[0] == "recv_bytes") + sendTextFrame("recv_bytes " + std::to_string(model.getRecvBytesTotal() / 1024)); + else if (tokens[0] == "kill" && tokens.count() == 2) { try @@ -244,7 +248,10 @@ void AdminSocketHandler::sendTextFrame(const std::string& message) { UnitWSD::get().onAdminQueryMessage(message); if (_isAuthenticated) + { + LOG_TRC("send admin text frame '" << message << "'"); sendMessage(message); + } else LOG_TRC("Skip sending message to non-authenticated client: '" << message << "'"); } @@ -387,7 +394,7 @@ void Admin::rescheduleCpuTimer(unsigned interval) wakeup(); } -unsigned Admin::getTotalMemoryUsage() +size_t Admin::getTotalMemoryUsage() { // To simplify and clarify this; since load, link and pre-init all // inside the forkit - we should account all of our fixed cost of @@ -427,6 +434,12 @@ void Admin::updateMemoryDirty(const std::string& docKey, int dirty) { _model.updateMemoryDirty(docKey, dirty); }); } +void Admin::addBytes(const std::string& docKey, uint64_t sent, uint64_t recv) +{ + addCallback([this, docKey, sent, recv] + { _model.addBytes(docKey, sent, recv); }); +} + void Admin::dumpState(std::ostream& os) { // FIXME: be more helpful ... diff --git a/wsd/Admin.hpp b/wsd/Admin.hpp index f9d8bb6a..2c77e391 100644 --- a/wsd/Admin.hpp +++ b/wsd/Admin.hpp @@ -69,7 +69,7 @@ public: /// Custom poll thread function void pollingThread() override; - unsigned getTotalMemoryUsage(); + size_t getTotalMemoryUsage(); void modificationAlert(const std::string& dockey, Poco::Process::PID pid, bool value); /// Update the Admin Model. @@ -99,6 +99,7 @@ public: void updateLastActivityTime(const std::string& docKey); void updateMemoryDirty(const std::string& docKey, int dirty); + void addBytes(const std::string& docKey, uint64_t sent, uint64_t recv); void dumpState(std::ostream& os) override; @@ -107,7 +108,7 @@ private: /// the Admin Poll thread. AdminModel _model; int _forKitPid; - long _lastTotalMemory; + size_t _lastTotalMemory; std::atomic<int> _memStatsTaskIntervalMs; std::atomic<int> _cpuStatsTaskIntervalMs; diff --git a/wsd/AdminModel.cpp b/wsd/AdminModel.cpp index 51b314ef..1ee088eb 100644 --- a/wsd/AdminModel.cpp +++ b/wsd/AdminModel.cpp @@ -373,6 +373,18 @@ void AdminModel::notify(const std::string& message) } } +void AdminModel::addBytes(const std::string& docKey, uint64_t sent, uint64_t recv) +{ + assertCorrectThread(); + + auto doc = _documents.find(docKey); + if(doc != _documents.end()) + doc->second.addBytes(sent, recv); + + _sentBytesTotal += sent; + _recvBytesTotal += recv; +} + void AdminModel::modificationAlert(const std::string& docKey, Poco::Process::PID pid, bool value) { assertCorrectThread(); diff --git a/wsd/AdminModel.hpp b/wsd/AdminModel.hpp index 1d86e827..ed83d8cd 100644 --- a/wsd/AdminModel.hpp +++ b/wsd/AdminModel.hpp @@ -55,7 +55,9 @@ public: _filename(filename), _memoryDirty(0), _start(std::time(nullptr)), - _lastActivity(_start) + _lastActivity(_start), + _sentBytes(0), + _recvBytes(0) { } @@ -88,6 +90,12 @@ public: void setModified(bool value) { _isModified = value; } bool getModifiedStatus() const { return _isModified; } + void addBytes(uint64_t sent, uint64_t recv) + { + _sentBytes += sent; + _recvBytes += recv; + } + std::string to_string() const; private: @@ -107,6 +115,9 @@ private: std::time_t _lastActivity; std::time_t _end = 0; std::map<std::time_t,std::string> _snapshots; + + /// Total bytes sent and recv'd by this document. + uint64_t _sentBytes, _recvBytes; }; /// An Admin session subscriber. @@ -203,6 +214,11 @@ public: void updateLastActivityTime(const std::string& docKey); void updateMemoryDirty(const std::string& docKey, int dirty); + void addBytes(const std::string& docKey, uint64_t sent, uint64_t recv); + + uint64_t getSentBytesTotal() { return _sentBytesTotal; } + uint64_t getRecvBytesTotal() { return _recvBytesTotal; } + private: std::string getMemStats(); @@ -224,6 +240,9 @@ private: std::list<unsigned> _cpuStats; unsigned _cpuStatsSize = 100; + uint64_t _sentBytesTotal; + uint64_t _recvBytesTotal; + /// We check the owner even in the release builds, needs to be always correct. std::thread::id _owner; }; diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp index ac7db55f..a80b9395 100644 --- a/wsd/DocumentBroker.cpp +++ b/wsd/DocumentBroker.cpp @@ -228,12 +228,34 @@ void DocumentBroker::pollThread() "per_document.idle_timeout_secs", 3600); std::string closeReason = "stopped"; + // Used to accumulate B/W deltas. + uint64_t adminSent = 0; + uint64_t adminRecv = 0; + auto lastBWUpdateTime = std::chrono::steady_clock::now(); + // Main polling loop goodness. while (!_stop && _poll->continuePolling() && !TerminationFlag) { _poll->poll(SocketPoll::DefaultPollTimeoutMs); const auto now = std::chrono::steady_clock::now(); + + if (std::chrono::duration_cast<std::chrono::milliseconds> + (now - lastBWUpdateTime).count() >= 5 * 1000) + { + lastBWUpdateTime = now; + uint64_t sent, recv; + getIOStats(sent, recv); + // send change since last notification. + Admin::instance().addBytes(getDocKey(), + // connection drop transiently reduces this. + std::max(sent - adminSent, uint64_t(0)), + std::max(recv - adminRecv, uint64_t(0))); + LOG_INF("Doc [" << _docKey << "] added sent: " << sent << " recv: " << recv << " bytes to totals"); + adminSent = sent; + adminRecv = recv; + } + if (_lastSaveTime < _lastSaveRequestTime && std::chrono::duration_cast<std::chrono::milliseconds> (now - _lastSaveRequestTime).count() <= COMMAND_TIMEOUT_MS) @@ -1461,7 +1483,7 @@ void DocumentBroker::dumpState(std::ostream& os) else os << "\n still loading..."; os << "\n sent: " << sent; - os << "\n recv?: " << recv; + os << "\n recv: " << recv; os << "\n modified?: " << _isModified; os << "\n jail id: " << _jailId; os << "\n filename: " << _filename; diff --git a/wsd/DocumentBroker.hpp b/wsd/DocumentBroker.hpp index 2c244fe1..6069b9c0 100644 --- a/wsd/DocumentBroker.hpp +++ b/wsd/DocumentBroker.hpp @@ -367,6 +367,7 @@ private: /// associated with this document. void pollThread(); + /// Sum the I/O stats from all connected sessions void getIOStats(uint64_t &sent, uint64_t &recv); private: diff --git a/wsd/protocol.txt b/wsd/protocol.txt index 7f43e472..4ecd8378 100644 --- a/wsd/protocol.txt +++ b/wsd/protocol.txt @@ -554,10 +554,13 @@ history } total_mem +sent_bytes +recv_bytes - Queries for total memory being consumed by the server in kilobytes. - This includes processes - loolwsd, loolforkit, and child processes - hosting various documents + Queries for total memory or bandwidth being consumed by the server + in kilobytes. For total_mem this includes processes - loolwsd, + loolforkit, and child processes hosting various documents. For + sent/recv_bytes this includes only external traffic. active_docs_count @@ -651,6 +654,8 @@ documents <pid> <filename> <number of views> <memory consumed> <elapsed time> <i Each set document attributes is separated by a newline. total_mem <memory> +sent_bytes <memory> +recv_bytes <memory> <memory> in kilobytes _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits