[Libreoffice-commits] online.git: loleaflet/admin.strings.js loleaflet/dist loleaflet/src wsd/Admin.cpp wsd/Admin.hpp wsd/AdminModel.cpp wsd/AdminModel.hpp wsd/DocumentBroker.cpp wsd/DocumentBroker.hpp wsd/protocol.txt

Michael Meeks michael.meeks at collabora.com
Sat Jun 3 21:56:37 UTC 2017


 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.meeks at 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
 


More information about the Libreoffice-commits mailing list