loleaflet/admin.strings.js                  |    1 
 loleaflet/dist/admin/adminAnalytics.html    |   12 +
 loleaflet/src/admin/AdminSocketAnalytics.js |  245 ++++++++++++++++++++++++++--
 wsd/Admin.cpp                               |   45 ++++-
 wsd/Admin.hpp                               |    6 
 wsd/AdminModel.cpp                          |   60 ++++++
 wsd/AdminModel.hpp                          |   14 +
 wsd/DocumentBroker.cpp                      |    4 
 8 files changed, 361 insertions(+), 26 deletions(-)

New commits:
commit 681138ab54ac03fbb26b1c2aa3ae7bcf9e7dde82
Author: Aditya Dewan <iit2015...@iiita.ac.in>
Date:   Sat Jun 10 06:58:16 2017 +0530

    tdf#106451 admin: graph to monitor network activity
    
    Change-Id: Id71ef4e2a9d16e72f4df442fbf646a39213b61d5
    Reviewed-on: https://gerrit.libreoffice.org/38621
    Reviewed-by: pranavk <pran...@collabora.co.uk>
    Tested-by: pranavk <pran...@collabora.co.uk>

diff --git a/loleaflet/admin.strings.js b/loleaflet/admin.strings.js
index 896dcbc3..26f232ba 100644
--- a/loleaflet/admin.strings.js
+++ b/loleaflet/admin.strings.js
@@ -27,6 +27,7 @@ l10nstrings.strKill = _('Kill');
 l10nstrings.strGraphs = _('Graphs');
 l10nstrings.strMemoryGraph = _('Memory Graph');
 l10nstrings.strCpuGraph = _('CPU Graph');
+l10nstrings.strNetGraph = _('Network Graph');
 l10nstrings.strSave = _('Save');
 l10nstrings.strMemoryStatsCachesize = _('Cache size of memory statistics');
 l10nstrings.strMemoryStatsInterval = _('Time interval of memory statistics (in 
ms)');
diff --git a/loleaflet/dist/admin/adminAnalytics.html 
b/loleaflet/dist/admin/adminAnalytics.html
index 10957f24..2dc97203 100644
--- a/loleaflet/dist/admin/adminAnalytics.html
+++ b/loleaflet/dist/admin/adminAnalytics.html
@@ -73,6 +73,11 @@
                 
<h4><script>document.write(l10nstrings.strCpuGraph)</script></h3>
               </a>
             </li>
+            <li>
+              <a href="#networkview" data-toggle="tab">
+                
<h4><script>document.write(l10nstrings.strNetGraph)</script></h3>
+              </a>
+            </li>
           </ul>
           <div class="tab-content graph-content">
             <div id="memview" class="active tab-pane">
@@ -89,6 +94,13 @@
                 </div>
               </div>
             </div>
+            <div id="networkview" class="tab-pane">
+              <div class="graph-container">
+                <div>
+                  <svg id="NetVisualisation" width="1010" height="510"></svg>
+                </div>
+              </div>
+            </div>
           </div>
         </div>
       </div>
diff --git a/loleaflet/src/admin/AdminSocketAnalytics.js 
b/loleaflet/src/admin/AdminSocketAnalytics.js
index b09348c2..72d5f275 100644
--- a/loleaflet/src/admin/AdminSocketAnalytics.js
+++ b/loleaflet/src/admin/AdminSocketAnalytics.js
@@ -12,6 +12,10 @@ var AdminSocketAnalytics = AdminSocketBase.extend({
 
        _memStatsData: [],
        _cpuStatsData: [],
+       _sentStatsData: [],
+       _sentAvgStats: [],
+       _recvStatsData: [],
+       _recvAvgStats: [],
 
        _memStatsSize: 0,
        _memStatsInterval: 0,
@@ -19,6 +23,10 @@ var AdminSocketAnalytics = AdminSocketBase.extend({
        _cpuStatsSize: 0,
        _cpuStatsInterval: 0,
 
+       _netAvgSize: 10,
+       _netStatsSize: 0,
+       _netStatsInterval: 0,
+
        _initStatsData: function(option, size, interval, reset) {
                var actualData;
 
@@ -36,14 +44,24 @@ var AdminSocketAnalytics = AdminSocketBase.extend({
                        this._memStatsData = actualData;
                else if (option === 'cpu')
                        this._cpuStatsData = actualData;
+               else if (option === 'sent')
+                       this._sentStatsData = actualData;
+               else if (option === 'recv')
+                       this._recvStatsData = actualData;
+               else if (option === 'sent_avg')
+                       this._sentAvgStats = actualData;
+               else if (option === 'recv_avg')
+                       this._recvAvgStats = actualData;
        },
 
        onSocketOpen: function() {
                // Base class' onSocketOpen handles authentication
                this.base.call(this);
 
-               this.socket.send('subscribe mem_stats cpu_stats settings');
+               this.socket.send('subscribe mem_stats cpu_stats sent_activity 
recv_activity settings');
                this.socket.send('settings');
+               this.socket.send('sent_activity');
+               this.socket.send('recv_activity');
                this.socket.send('mem_stats');
                this.socket.send('cpu_stats');
        },
@@ -60,6 +78,13 @@ var AdminSocketAnalytics = AdminSocketBase.extend({
        _xCpuScale: null,
        _yCpuScale: null,
 
+       _d3NetXAxis: null,
+       _d3NetYAxis: null,
+       _d3NetSentLine: null,
+       _d3NetRecvLine: null,
+       _xNetScale: null,
+       _yNetScale: null,
+
        _graphWidth: 1000,
        _graphHeight: 500,
        _graphMargins: {
@@ -70,11 +95,14 @@ var AdminSocketAnalytics = AdminSocketBase.extend({
        },
 
        _setUpAxis: function(option) {
+               var data, xScale, yScale, d3XAxis, d3Line;
 
                if (option === 'mem')
                        data = this._memStatsData;
                else if (option === 'cpu')
                        data = this._cpuStatsData;
+               else if (option === 'net')
+                       data = this._sentAvgStats.concat(this._recvAvgStats);
 
                xScale = d3.scale.linear().range([this._graphMargins.left, 
this._graphWidth - this._graphMargins.right]).domain([d3.min(data, function(d) {
                        return d.time;
@@ -133,11 +161,27 @@ var AdminSocketAnalytics = AdminSocketBase.extend({
                                .orient('left');
                        this._d3CpuLine = d3Line;
                }
+               else if (option === 'net') {
+                       this._xNetScale = xScale;
+                       this._yNetScale = yScale;
+                       this._d3NetXAxis = d3XAxis;
+                       this._d3NetYAxis = d3.svg.axis()
+                               .scale(this._yNetScale)
+                               .tickFormat(function (d) {
+                                       return Util.humanizeMem(d) + '/sec';
+                               })
+                               .orient('left');
+                       this._d3NetSentLine = d3Line;
+                       this._d3NetRecvLine = d3Line;
+
+               }
        },
 
        _createGraph: function(option) {
+               var vis, xAxis, yAxis, line, data;
+
                if (option === 'mem') {
-                       var vis = d3.select('#MemVisualisation');
+                       vis = d3.select('#MemVisualisation');
                        this._setUpAxis('mem');
                        xAxis = this._d3MemXAxis;
                        yAxis = this._d3MemYAxis;
@@ -145,13 +189,51 @@ var AdminSocketAnalytics = AdminSocketBase.extend({
                        data = this._memStatsData;
                }
                else if (option === 'cpu') {
-                       var vis = d3.select('#CpuVisualisation');
+                       vis = d3.select('#CpuVisualisation');
                        this._setUpAxis('cpu');
                        xAxis = this._d3CpuXAxis;
                        yAxis = this._d3CpuYAxis;
                        line = this._d3CpuLine;
                        data = this._cpuStatsData;
                }
+               else if (option === 'net') {
+                       vis = d3.select('#NetVisualisation');
+                       this._setUpAxis('net');
+                       xAxis = this._d3NetXAxis;
+                       yAxis = this._d3NetYAxis;
+
+                       var legend = vis.append('g')
+                               .attr('x', this._graphWidth - 70)
+                               .attr('y', 50)
+                               .style('font-size', '17px');
+
+                       var legendData = [
+                               {
+                                       text: 'Recieved',
+                                       color: 'red'
+                               },
+                               {
+                                       text: 'Sent',
+                                       color: 'green'
+                               }
+                       ];
+                       var legendSpacing = 20;
+
+                       for (var i = legendData.length - 1; i >= 0; i--) {
+
+                               legend.append('text')
+                                       .attr('x', this._graphWidth - 70)
+                                       .attr('y', 80 + i * legendSpacing)
+                                       .text(legendData[i].text);
+                               legend.append('rect')
+                                       .attr('x', this._graphWidth - 90)
+                                       .attr('y', 67 + i * legendSpacing)
+                                       .attr('width', 15)
+                                       .attr('height', 15)
+                                       .style('fill', legendData[i].color)
+                                       .style('stroke', 'black');
+                       }
+               }
 
                vis.append('svg:g')
                .attr('class', 'x-axis')
@@ -163,15 +245,45 @@ var AdminSocketAnalytics = AdminSocketBase.extend({
                .attr('transform', 'translate(' + this._graphMargins.left + 
',0)')
                .call(yAxis);
 
-               vis.append('svg:path')
-                       .attr('d', line(data))
-                       .attr('class', 'line')
-                       .attr('stroke', 'blue')
-                       .attr('stroke-width', 2)
-                       .attr('fill', 'none');
+               if (option === 'cpu' || option === 'mem') {
+
+                       vis.append('svg:path')
+                               .attr('d', line(data))
+                               .attr('class', 'line')
+                               .attr('stroke', 'blue')
+                               .attr('stroke-width', 2)
+                               .attr('fill', 'none');
+               }
+               else if (option === 'net') {
+
+                       vis.append('svg:path')
+                               .attr('d', 
this._d3NetSentLine(this._sentAvgStats))
+                               .attr('class', 'lineSent')
+                               .attr('stroke', 'red')
+                               .attr('stroke-width', 2)
+                               .attr('fill', 'none');
+
+                       vis.append('svg:path')
+                               .attr('d', 
this._d3NetRecvLine(this._recvAvgStats))
+                               .attr('class', 'lineRecv')
+                               .attr('stroke', 'green')
+                               .attr('stroke-width', 2)
+                               .attr('fill', 'none');
+               }
+
        },
 
-       _addNewData: function(oldData, newData) {
+       _addNewData: function(oldData, newData, option) {
+               var size;
+               if (option === 'mem')
+                       size = this._memStatsSize;
+               else if (option === 'cpu')
+                       size = this._cpuStatsSize;
+               else if (option === 'sent' || option === 'recv')
+                       size = this._netStatsSize;
+               else if (option === 'sent_avg' || option === 'recv_avg')
+                       size = this._netStatsSize - this._netAvgSize + 1;
+
                // make a space for new data
                for (var i = oldData.length - 1; i > 0; i--) {
                        oldData[i].time = oldData[i - 1].time;
@@ -181,13 +293,13 @@ var AdminSocketAnalytics = AdminSocketBase.extend({
                oldData.push({time: 0, value: parseInt(newData)});
 
                // remove extra items
-               if (oldData.length > this._memStatsSize) {
+               if (oldData.length > size) {
                        oldData.shift();
                }
        },
 
        _updateMemGraph: function() {
-               svg = d3.select('#MemVisualisation');
+               var svg = d3.select('#MemVisualisation');
 
                this._setUpAxis('mem');
 
@@ -202,7 +314,7 @@ var AdminSocketAnalytics = AdminSocketBase.extend({
        },
 
        _updateCpuGraph: function() {
-               svg = d3.select('#CpuVisualisation');
+               var svg = d3.select('#CpuVisualisation');
 
                this._setUpAxis('cpu');
 
@@ -216,6 +328,51 @@ var AdminSocketAnalytics = AdminSocketBase.extend({
                .call(this._d3CpuYAxis);
        },
 
+       _updateNetGraph: function() {
+               var svg = d3.select('#NetVisualisation');
+
+               this._setUpAxis('net');
+
+               svg.select('.lineSent')
+               .attr('d', this._d3NetSentLine(this._sentAvgStats));
+               svg.select('.lineRecv')
+               .attr('d', this._d3NetRecvLine(this._recvAvgStats));
+
+               svg.select('.x-axis')
+               .call(this._d3NetXAxis);
+
+               svg.select('.y-axis')
+               .call(this._d3NetYAxis);
+       },
+
+       _updateAverage: function(option, reset) {
+               var data, res, tempSum;
+               if (option === 'sent') {
+                       data = this._sentStatsData;
+                       res = this._sentAvgStats;
+               }
+               else if (option === 'recv') {
+                       data = this._recvStatsData;
+                       res = this._recvAvgStats;
+               }
+
+               if (reset) {
+                       for (i = 0; i <= this._netStatsSize - this._netAvgSize; 
i++) {
+                               tempSum = 0;
+                               for (j = 0; j < this._netAvgSize; j++) {
+                                       tempSum += data[i + j].value;
+                               }
+                               tempSum /= this._netAvgSize;
+                               res[i].value = tempSum;
+                       }
+               }
+               else {
+                       tempSum = res[res.length - 1].value + (data[data.length 
- 1].value - data[data.length - 1 - this._netAvgSize].value) / this._netAvgSize;
+
+                       this._addNewData(res, tempSum, 'sent_avg');
+               }
+       },
+
        onSocketMessage: function(e) {
                var textMsg;
                if (typeof e.data === 'string') {
@@ -249,6 +406,12 @@ var AdminSocketAnalytics = AdminSocketBase.extend({
                                else if (setting[0] === 'cpu_stats_interval') {
                                        cpuStatsInterval = parseInt(setting[1]);
                                }
+                               else if (setting[0] === 'net_stats_size') {
+                                       this._netStatsSize = 
parseInt(setting[1]);
+                               }
+                               else if (setting[0] === 'net_stats_interval') {
+                                       this._netStatsInterval = 
parseInt(setting[1]);
+                               }
                        }
 
                        // Fix the axes according to changed data
@@ -284,6 +447,12 @@ var AdminSocketAnalytics = AdminSocketBase.extend({
 
                        this._cpuStatsSize = cpuStatsSize;
                        this._cpuStatsInterval = cpuStatsInterval;
+
+                       this._initStatsData('sent', this._netStatsSize, 
this._netStatsInterval, true);
+                       this._initStatsData('recv', this._netStatsSize, 
this._netStatsInterval, true);
+                       this._initStatsData('sent_avg', this._netStatsSize - 
this._netAvgSize + 1, this._netStatsInterval, true);
+                       this._initStatsData('recv_avg', this._netStatsSize - 
this._netAvgSize + 1, this._netStatsInterval, true);
+
                }
                else if (textMsg.startsWith('mem_stats')) {
                        textMsg = textMsg.split(' ')[1];
@@ -299,7 +468,7 @@ var AdminSocketAnalytics = AdminSocketBase.extend({
                        else {
                                // this is a notification data; append to 
_memStatsData
                                data = textMsg.trim();
-                               this._addNewData(this._memStatsData, data);
+                               this._addNewData(this._memStatsData, data, 
'mem');
                                this._updateMemGraph();
                        }
                }
@@ -318,10 +487,54 @@ var AdminSocketAnalytics = AdminSocketBase.extend({
                        else {
                                // this is a notification data; append to 
_cpuStatsData
                                data = textMsg.trim();
-                               this._addNewData(this._cpuStatsData, data);
+                               this._addNewData(this._cpuStatsData, data, 
'cpu');
                                this._updateCpuGraph();
                        }
                }
+               else if (textMsg.startsWith('sent_activity')) {
+                       textMsg = textMsg.split(' ')[1];
+                       if (textMsg.endsWith(',')) {
+                               // This is the result of query, not notification
+                               data = textMsg.substring(0, textMsg.length - 
1).split(',');
+
+                               for (i = this._sentStatsData.length - 1, j = 
data.length - 1; i >= 0 && j >= 0; i--, j--) {
+                                       this._sentStatsData[i].value = 
parseInt(data[j]) / this._netStatsInterval;
+                               }
+                               this._updateAverage('sent', true);
+
+                               if ($('#NetVisualisation').html() === '')
+                                       this._createGraph('net');
+                       }
+                       else {
+                               // this is a notification data; append to 
_sentStatsData
+                               data = textMsg.trim();
+                               this._addNewData(this._sentStatsData, 
parseInt(data) / this._netStatsInterval, 'sent');
+                               this._updateAverage('sent', false);
+                               this._updateNetGraph();
+                       }
+               }
+               else if (textMsg.startsWith('recv_activity')) {
+                       textMsg = textMsg.split(' ')[1];
+                       if (textMsg.endsWith(',')) {
+                               // This is the result of query, not notification
+                               data = textMsg.substring(0, textMsg.length - 
1).split(',');
+
+                               for (i = this._recvStatsData.length - 1, j = 
data.length - 1; i >= 0 && j >= 0; i--, j--) {
+                                       this._recvStatsData[i].value = 
parseInt(data[j]) / this._netStatsInterval;
+                               }
+                               this._updateAverage('recv', true);
+
+                               if ($('#NetVisualisation').html() === '')
+                                       this._createGraph('net');
+                       }
+                       else {
+                               // this is a notification data; append to 
_recvStatsData
+                               data = textMsg.trim();
+                               this._addNewData(this._recvStatsData, 
parseInt(data) / this._netStatsInterval, 'recv');
+                               this._updateAverage('recv', false);
+                               this._updateNetGraph();
+                       }
+               }
        },
 
        onSocketClose: function() {
@@ -331,4 +544,4 @@ var AdminSocketAnalytics = AdminSocketBase.extend({
 
 Admin.Analytics = function(host) {
        return new AdminSocketAnalytics(host);
-};
+};
\ No newline at end of file
diff --git a/wsd/Admin.cpp b/wsd/Admin.cpp
index 3d4a8fb6..deeaecc0 100644
--- a/wsd/Admin.cpp
+++ b/wsd/Admin.cpp
@@ -104,7 +104,9 @@ void AdminSocketHandler::handleMessage(bool /* fin */, 
WSOpCode /* code */,
              tokens[0] == "active_users_count" ||
              tokens[0] == "active_docs_count" ||
              tokens[0] == "mem_stats" ||
-             tokens[0] == "cpu_stats")
+             tokens[0] == "cpu_stats" ||
+             tokens[0] == "sent_activity" ||
+             tokens[0] == "recv_activity")
     {
         const std::string result = model.query(tokens[0]);
         if (!result.empty())
@@ -170,7 +172,9 @@ void AdminSocketHandler::handleMessage(bool /* fin */, 
WSOpCode /* code */,
             << "mem_stats_size=" << model.query("mem_stats_size") << ' '
             << "mem_stats_interval=" << 
std::to_string(_admin->getMemStatsInterval()) << ' '
             << "cpu_stats_size="  << model.query("cpu_stats_size") << ' '
-            << "cpu_stats_interval=" << 
std::to_string(_admin->getCpuStatsInterval()) << ' ';
+            << "cpu_stats_interval=" << 
std::to_string(_admin->getCpuStatsInterval()) << ' '
+            << "net_stats_size=" << model.query("net_stats_size") << ' '
+            << "net_stats_interval=" << 
std::to_string(_admin->getNetStatsInterval()) << ' ';
 
         const DocProcSettings& docProcSettings = 
_admin->getDefDocProcSettings();
         oss << "limit_virt_mem_mb=" << docProcSettings.LimitVirtMemMb << ' '
@@ -321,8 +325,11 @@ Admin::Admin() :
     _forKitWritePipe(-1),
     _lastTotalMemory(0),
     _lastJiffies(0),
+    _lastSentCount(0),
+    _lastRecvCount(0),
     _memStatsTaskIntervalMs(5000),
-    _cpuStatsTaskIntervalMs(2000)
+    _cpuStatsTaskIntervalMs(2000),
+    _networkStatsIntervalMs(5000)
 {
     LOG_INF("Admin ctor.");
 
@@ -338,28 +345,30 @@ Admin::~Admin()
 
 void Admin::pollingThread()
 {
-    std::chrono::steady_clock::time_point lastCPU, lastMem;
+    std::chrono::steady_clock::time_point lastCPU, lastMem, lastNet;
 
     _model.setThreadOwner(std::this_thread::get_id());
 
     lastCPU = std::chrono::steady_clock::now();
     lastMem = lastCPU;
+    lastNet = lastCPU;
 
     while (!_stop && !TerminationFlag && !ShutdownRequestFlag)
     {
         std::chrono::steady_clock::time_point now = 
std::chrono::steady_clock::now();
+
         int cpuWait = _cpuStatsTaskIntervalMs -
             std::chrono::duration_cast<std::chrono::milliseconds>(now - 
lastCPU).count();
-
-        size_t currentJiffies = getTotalCpuUsage();
         if (cpuWait <= 0)
         {
+            size_t currentJiffies = getTotalCpuUsage();
             auto cpuPercent = 100 * 1000 * currentJiffies / (sysconf 
(_SC_CLK_TCK) * _cpuStatsTaskIntervalMs);
             _model.addCpuStats(cpuPercent);
 
             lastCPU = now;
             cpuWait += _cpuStatsTaskIntervalMs;
         }
+
         int memWait = _memStatsTaskIntervalMs -
             std::chrono::duration_cast<std::chrono::milliseconds>(now - 
lastMem).count();
         if (memWait <= 0)
@@ -377,8 +386,25 @@ void Admin::pollingThread()
             memWait += _memStatsTaskIntervalMs;
         }
 
+        int netWait = _networkStatsIntervalMs -
+            std::chrono::duration_cast<std::chrono::milliseconds>(now - 
lastNet).count();
+        if(netWait <= 0)
+        {
+            uint64_t sentCount = _model.getSentBytesTotal();
+            uint64_t recvCount = _model.getRecvBytesTotal();
+
+            _model.addSentStats(sentCount - _lastSentCount);
+            _model.addRecvStats(recvCount - _lastRecvCount);
+
+            LOG_TRC("Total Data sent: " << sentCount << ", recv: " << 
recvCount);
+            _lastRecvCount = recvCount;
+            _lastSentCount = sentCount;
+
+            lastNet = now;
+            netWait += _networkStatsIntervalMs;
+        }
         // Handle websockets & other work.
-        int timeout = std::min(cpuWait, memWait);
+        int timeout = std::min(std::min(cpuWait, memWait), netWait);
         LOG_TRC("Admin poll for " << timeout << "ms");
         poll(timeout);
     }
@@ -463,6 +489,11 @@ unsigned Admin::getCpuStatsInterval()
     return _cpuStatsTaskIntervalMs;
 }
 
+unsigned Admin::getNetStatsInterval()
+{
+    return _networkStatsIntervalMs;
+}
+
 AdminModel& Admin::getModel()
 {
     return _model;
diff --git a/wsd/Admin.hpp b/wsd/Admin.hpp
index 5ca87572..18acab4a 100644
--- a/wsd/Admin.hpp
+++ b/wsd/Admin.hpp
@@ -95,6 +95,8 @@ public:
 
     unsigned getCpuStatsInterval();
 
+    unsigned getNetStatsInterval();
+
     void rescheduleMemTimer(unsigned interval);
 
     void rescheduleCpuTimer(unsigned interval);
@@ -124,11 +126,13 @@ private:
     int _forKitWritePipe;
     size_t _lastTotalMemory;
     size_t _lastJiffies;
+    uint64_t _lastSentCount;
+    uint64_t _lastRecvCount;
 
     std::atomic<int> _memStatsTaskIntervalMs;
     std::atomic<int> _cpuStatsTaskIntervalMs;
-
     DocProcSettings _defDocProcSettings;
+    std::atomic<int> _networkStatsIntervalMs;
 };
 
 #endif
diff --git a/wsd/AdminModel.cpp b/wsd/AdminModel.cpp
index bcbdd1d1..073d886c 100644
--- a/wsd/AdminModel.cpp
+++ b/wsd/AdminModel.cpp
@@ -238,6 +238,18 @@ std::string AdminModel::query(const std::string& command)
     {
         return std::to_string(_cpuStatsSize);
     }
+    else if (token == "sent_activity")
+    {
+        return getSentActivity();
+    }
+    else if (token == "recv_activity")
+    {
+        return getRecvActivity();
+    }
+    else if (token == "net_stats_size")
+    {
+        return std::to_string(std::max(_sentStatsSize, _recvStatsSize));
+    }
 
     return std::string("");
 }
@@ -349,6 +361,28 @@ void AdminModel::addCpuStats(unsigned cpuUsage)
     notify("cpu_stats " + std::to_string(cpuUsage));
 }
 
+void AdminModel::addSentStats(uint64_t sent)
+{
+    assertCorrectThread();
+
+    _sentStats.push_back(sent);
+    if (_sentStats.size() > _sentStatsSize)
+        _sentStats.pop_front();
+
+    notify("sent_activity " + std::to_string(sent));
+}
+
+void AdminModel::addRecvStats(uint64_t recv)
+{
+    assertCorrectThread();
+
+    _recvStats.push_back(recv);
+    if (_recvStats.size() > _recvStatsSize)
+        _recvStats.pop_front();
+
+    notify("recv_activity " + std::to_string(recv));
+}
+
 void AdminModel::setCpuStatsSize(unsigned size)
 {
     assertCorrectThread();
@@ -550,6 +584,32 @@ std::string AdminModel::getCpuStats()
     return oss.str();
 }
 
+std::string AdminModel::getSentActivity()
+{
+    assertCorrectThread();
+
+    std::ostringstream oss;
+    for (const auto& i: _sentStats)
+    {
+        oss << i << ',';
+    }
+
+    return oss.str();
+}
+
+std::string AdminModel::getRecvActivity()
+{
+    assertCorrectThread();
+
+    std::ostringstream oss;
+    for (const auto& i: _recvStats)
+    {
+        oss << i << ',';
+    }
+
+    return oss.str();
+}
+
 unsigned AdminModel::getTotalActiveViews()
 {
     assertCorrectThread();
diff --git a/wsd/AdminModel.hpp b/wsd/AdminModel.hpp
index 96231bda..e9eed373 100644
--- a/wsd/AdminModel.hpp
+++ b/wsd/AdminModel.hpp
@@ -221,6 +221,10 @@ public:
 
     void addCpuStats(unsigned cpuUsage);
 
+    void addSentStats(uint64_t sent);
+
+    void addRecvStats(uint64_t recv);
+
     void setCpuStatsSize(unsigned size);
 
     void setMemStatsSize(unsigned size);
@@ -243,6 +247,10 @@ public:
 private:
     std::string getMemStats();
 
+    std::string getSentActivity();
+
+    std::string getRecvActivity();
+
     std::string getCpuStats();
 
     unsigned getTotalActiveViews();
@@ -261,6 +269,12 @@ private:
     std::list<unsigned> _cpuStats;
     unsigned _cpuStatsSize = 100;
 
+    std::list<unsigned> _sentStats;
+    unsigned _sentStatsSize = 100;
+
+    std::list<unsigned> _recvStats;
+    unsigned _recvStatsSize = 100;
+
     uint64_t _sentBytesTotal;
     uint64_t _recvBytesTotal;
 
diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index 844bff78..d4ac586a 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -249,8 +249,8 @@ void DocumentBroker::pollThread()
             // 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)));
+                                       (sent > adminSent ? (sent - adminSent): 
uint64_t(0)),
+                                       (recv > adminRecv ? (recv - adminRecv): 
uint64_t(0)));
             LOG_INF("Doc [" << _docKey << "] added sent: " << sent << " recv: 
" << recv << " bytes to totals");
             adminSent = sent;
             adminRecv = recv;
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to