zookeeper-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ph...@apache.org
Subject zookeeper git commit: ZOOKEEPER-2940: Deal with maxbuffer as it relates to large requests from clients
Date Wed, 11 Jul 2018 23:38:05 GMT
Repository: zookeeper
Updated Branches:
  refs/heads/master c2e7ed1e6 -> 328b9de01


ZOOKEEPER-2940: Deal with maxbuffer as it relates to large requests from clients

https://issues.apache.org/jira/browse/ZOOKEEPER-2940

This PR covers the other part of Jute buffer monitoring which relates to client response sizes.

`jute.maxbuffer` is often set too small or the default (4MB) value is not enough to receive large responses from the server which causes the client unable to operate. e.g. `getChildren()` on a node which has lots of children or execution of a large multi.

These new metrics lets operators to monitor the size of generated responses to get an idea on how to properly set client's `jute.maxbuffer`.

The other part of monitoring which relates to proposal size has already been merged https://github.com/apache/zookeeper/pull/415

Author: Andor Molnar <andor@cloudera.com>

Reviewers: phunt@apache.org

Closes #466 from anmolnar/ZOOKEEPER-2940 and squashes the following commits:

29224d021 [Andor Molnar] ZOOKEEPER-2940. Test fixes
486d4961d [Andor Molnar] ZOOKEEPER-2940. Removed support of 4lw commands, because master is targeted
60916e09e [Andor Molnar] ZOOKEEPER-2940. Code review fixes
b39c4c815 [Andor Molnar] ZOOKEEPER-2940. Code review: variable names renamed to proposalStats
87e72ff31 [Andor Molnar] ZOOKEEPER-2940. Some code review cleanups
6f0adb124 [Andor Molnar] ZOOKEEPER-2940. Code review fixes: stats class renamed, added comments to unit test asserts, updated docs
bcb6d4ca5 [Andor Molnar] ZOOKEEPER-2940. Added new metrics to python files
77a5f0aa8 [Andor Molnar] ZOOKEEPER-2940. Fixed failing unit tests
2def61c30 [Andor Molnar] ZOOKEEPER-2940. Track size of client responses

Change-Id: I68df371097cc355b1f41b8dbb0168da4fa5dee43


Project: http://git-wip-us.apache.org/repos/asf/zookeeper/repo
Commit: http://git-wip-us.apache.org/repos/asf/zookeeper/commit/328b9de0
Tree: http://git-wip-us.apache.org/repos/asf/zookeeper/tree/328b9de0
Diff: http://git-wip-us.apache.org/repos/asf/zookeeper/diff/328b9de0

Branch: refs/heads/master
Commit: 328b9de0152f987429534c8adcb2ce2866c5733e
Parents: c2e7ed1
Author: Andor Molnar <andor@cloudera.com>
Authored: Wed Jul 11 16:33:51 2018 -0700
Committer: Patrick Hunt <phunt@apache.org>
Committed: Wed Jul 11 16:35:55 2018 -0700

----------------------------------------------------------------------
 docs/index.pdf                                  | Bin 12657 -> 12657 bytes
 docs/javaExample.pdf                            | Bin 33818 -> 33818 bytes
 docs/linkmap.pdf                                | Bin 10826 -> 10826 bytes
 docs/recipes.pdf                                | Bin 33856 -> 33856 bytes
 docs/zookeeperAdmin.html                        |  39 +++++++-
 docs/zookeeperAdmin.pdf                         | Bin 101979 -> 104344 bytes
 docs/zookeeperHierarchicalQuorums.pdf           | Bin 6654 -> 6654 bytes
 docs/zookeeperInternals.pdf                     | Bin 48811 -> 48811 bytes
 docs/zookeeperJMX.pdf                           | Bin 16475 -> 16475 bytes
 docs/zookeeperObservers.pdf                     | Bin 12868 -> 12868 bytes
 docs/zookeeperOver.pdf                          | Bin 302467 -> 302467 bytes
 docs/zookeeperProgrammers.html                  |   4 +
 docs/zookeeperProgrammers.pdf                   | Bin 148444 -> 149024 bytes
 docs/zookeeperQuotas.pdf                        | Bin 11184 -> 11184 bytes
 docs/zookeeperReconfig.pdf                      | Bin 62192 -> 62192 bytes
 docs/zookeeperStarted.pdf                       | Bin 28078 -> 28078 bytes
 docs/zookeeperTutorial.pdf                      | Bin 34212 -> 34212 bytes
 src/contrib/monitoring/check_zookeeper.py       |   9 +-
 src/contrib/monitoring/ganglia/zookeeper.pyconf |   3 +
 .../monitoring/ganglia/zookeeper_ganglia.py     |   5 +-
 .../org/apache/zookeeper/ClientCnxnSocket.java  |   2 +-
 .../apache/zookeeper/server/NIOServerCnxn.java  |  20 +----
 .../zookeeper/server/NettyServerCnxn.java       |  19 +---
 .../org/apache/zookeeper/server/ServerCnxn.java |  30 ++++++-
 .../apache/zookeeper/server/ServerStats.java    |  15 ++++
 .../zookeeper/server/ZooKeeperServerBean.java   |  15 ++++
 .../zookeeper/server/ZooKeeperServerMXBean.java |  15 ++++
 .../apache/zookeeper/server/admin/Commands.java |  14 ++-
 .../server/command/MonitorCommand.java          |   6 +-
 .../zookeeper/server/command/StatCommand.java   |   4 +-
 .../zookeeper/server/quorum/BufferStats.java    |  89 +++++++++++++++++++
 .../apache/zookeeper/server/quorum/Leader.java  |  10 +--
 .../zookeeper/server/quorum/LeaderBean.java     |   6 +-
 .../zookeeper/server/quorum/ProposalStats.java  |  71 ---------------
 .../zookeeper/server/NIOServerCnxnTest.java     |  25 +++++-
 .../zookeeper/server/NettyServerCnxnTest.java   |  23 +++++
 .../zookeeper/server/admin/CommandsTest.java    |  13 ++-
 .../server/quorum/BufferStatsTest.java          |  58 ++++++++++++
 .../server/quorum/ProposalStatsTest.java        |  58 ------------
 .../server/quorum/StatCommandTest.java          |   5 +-
 .../server/quorum/StatResetCommandTest.java     |   6 +-
 .../content/xdocs/zookeeperAdmin.xml            |   3 +
 42 files changed, 368 insertions(+), 199 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/docs/index.pdf
----------------------------------------------------------------------
diff --git a/docs/index.pdf b/docs/index.pdf
index 2a23554..91d9c4f 100644
Binary files a/docs/index.pdf and b/docs/index.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/docs/javaExample.pdf
----------------------------------------------------------------------
diff --git a/docs/javaExample.pdf b/docs/javaExample.pdf
index 3ca642d..0985e53 100644
Binary files a/docs/javaExample.pdf and b/docs/javaExample.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/docs/linkmap.pdf
----------------------------------------------------------------------
diff --git a/docs/linkmap.pdf b/docs/linkmap.pdf
index c3cace7..d4c896a 100644
Binary files a/docs/linkmap.pdf and b/docs/linkmap.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/docs/recipes.pdf
----------------------------------------------------------------------
diff --git a/docs/recipes.pdf b/docs/recipes.pdf
index 28650c7..5acb24f 100644
Binary files a/docs/recipes.pdf and b/docs/recipes.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/docs/zookeeperAdmin.html
----------------------------------------------------------------------
diff --git a/docs/zookeeperAdmin.html b/docs/zookeeperAdmin.html
index e03db49..dacbcc2 100644
--- a/docs/zookeeperAdmin.html
+++ b/docs/zookeeperAdmin.html
@@ -638,7 +638,9 @@ server.3=zoo3:2888:3888</pre>
           consists of a single line containing only the text of that machine's
           id. So <span class="codefrag filename">myid</span> of server 1 would contain the text
           "1" and nothing else. The id must be unique within the
-          ensemble and should have a value between 1 and 255.</p>
+          ensemble and should have a value between 1 and 255. <strong>IMPORTANT:</strong> if you
+          enable extended features such as TTL Nodes (see below) the id must be
+          between 1 and 254 due to internal limitations.</p>
         
 </li>
 
@@ -1345,6 +1347,37 @@ server.3=zoo3:2888:3888</pre>
               feature. Default is "true"</p>
 </dd>
 
+          
+<dt>
+<term>zookeeper.extendedTypesEnabled</term>
+</dt>
+<dd>
+<p>(Java system property only: <strong>zookeeper.extendedTypesEnabled</strong>)</p>
+<p>
+<strong>New in 3.5.4, 3.6.0:</strong> Define to "true" to enable
+              extended features such as the creation of <a href="zookeeperProgrammers.html#TTL+Nodes">TTL Nodes</a>.
+              They are disabled by default. IMPORTANT: when enabled server IDs must
+              be less than 255 due to internal limitations.
+              </p>
+</dd>
+
+          
+<dt>
+<term>zookeeper.emulate353TTLNodes</term>
+</dt>
+<dd>
+<p>(Java system property only: <strong>zookeeper.emulate353TTLNodes</strong>)</p>
+<p>
+<strong>New in 3.5.4, 3.6.0:</strong> Due to
+                <a href="https://issues.apache.org/jira/browse/ZOOKEEPER-2901">ZOOKEEPER-2901</a> TTL nodes
+                created in version 3.5.3 are not supported in 3.5.4/3.6.0. However, a workaround is provided via the
+                zookeeper.emulate353TTLNodes system property. If you used TTL nodes in ZooKeeper 3.5.3 and need to maintain
+                compatibility set <strong>zookeeper.emulate353TTLNodes</strong> to "true" in addition to
+                <strong>zookeeper.extendedTypesEnabled</strong>. NOTE: due to the bug, server IDs
+                must be 127 or less. Additionally, the maximum support TTL value is 1099511627775 which is smaller
+                than what was allowed in 3.5.3 (1152921504606846975)</p>
+</dd>
+
         
 </dl>
 <a name="sc_clusterOptions"></a>
@@ -2216,6 +2249,7 @@ server.3=zoo3:2888:3888</pre>
               zk_min_latency  0
               zk_packets_received 70
               zk_packets_sent 69
+              zk_num_alive_connections	1
               zk_outstanding_requests 0
               zk_server_state leader
               zk_znode_count   4
@@ -2227,6 +2261,9 @@ server.3=zoo3:2888:3888</pre>
               zk_pending_syncs    0               - only exposed by the Leader
               zk_open_file_descriptor_count 23    - only available on Unix platforms
               zk_max_file_descriptor_count 1024   - only available on Unix platforms
+              zk_last_proposal_size 23
+              zk_min_proposal_size 23
+              zk_max_proposal_size 64
               </pre>
 <p>The output is compatible with java properties format and the content 
               may change over time (new keys added). Your scripts should expect changes.</p>

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/docs/zookeeperAdmin.pdf
----------------------------------------------------------------------
diff --git a/docs/zookeeperAdmin.pdf b/docs/zookeeperAdmin.pdf
index 7c9aec4..54460c8 100644
Binary files a/docs/zookeeperAdmin.pdf and b/docs/zookeeperAdmin.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/docs/zookeeperHierarchicalQuorums.pdf
----------------------------------------------------------------------
diff --git a/docs/zookeeperHierarchicalQuorums.pdf b/docs/zookeeperHierarchicalQuorums.pdf
index 0ee89d9..db88ba8 100644
Binary files a/docs/zookeeperHierarchicalQuorums.pdf and b/docs/zookeeperHierarchicalQuorums.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/docs/zookeeperInternals.pdf
----------------------------------------------------------------------
diff --git a/docs/zookeeperInternals.pdf b/docs/zookeeperInternals.pdf
index 93b9cdd..32bd3e8 100644
Binary files a/docs/zookeeperInternals.pdf and b/docs/zookeeperInternals.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/docs/zookeeperJMX.pdf
----------------------------------------------------------------------
diff --git a/docs/zookeeperJMX.pdf b/docs/zookeeperJMX.pdf
index e115b29..0634715 100644
Binary files a/docs/zookeeperJMX.pdf and b/docs/zookeeperJMX.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/docs/zookeeperObservers.pdf
----------------------------------------------------------------------
diff --git a/docs/zookeeperObservers.pdf b/docs/zookeeperObservers.pdf
index ced39d8..5369f25 100644
Binary files a/docs/zookeeperObservers.pdf and b/docs/zookeeperObservers.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/docs/zookeeperOver.pdf
----------------------------------------------------------------------
diff --git a/docs/zookeeperOver.pdf b/docs/zookeeperOver.pdf
index f88b2ba..917ec15 100644
Binary files a/docs/zookeeperOver.pdf and b/docs/zookeeperOver.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/docs/zookeeperProgrammers.html
----------------------------------------------------------------------
diff --git a/docs/zookeeperProgrammers.html b/docs/zookeeperProgrammers.html
index 6eb41bd..45d8b2f 100644
--- a/docs/zookeeperProgrammers.html
+++ b/docs/zookeeperProgrammers.html
@@ -596,6 +596,10 @@ document.write("Last Published: " + document.lastModified);
           you can optionally set a TTL in milliseconds for the znode. If the znode
           is not modified within the TTL and has no children it will become a candidate
           to be deleted by the server at some point in the future.</p>
+<p>Note: TTL Nodes must be enabled via System property as
+        they are disabled by default. See the <a href="zookeeperAdmin.html#sc_configuration">Administrator's
+        Guide</a> for details. If you attempt to create TTL Nodes without the proper System property set the server
+        will throw <em>KeeperException.UnimplementedException</em>.</p>
 <a name="sc_timeInZk"></a>
 <h3 class="h4">Time in ZooKeeper</h3>
 <p>ZooKeeper tracks time multiple ways:</p>

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/docs/zookeeperProgrammers.pdf
----------------------------------------------------------------------
diff --git a/docs/zookeeperProgrammers.pdf b/docs/zookeeperProgrammers.pdf
index bbe0be8..ffff27e 100644
Binary files a/docs/zookeeperProgrammers.pdf and b/docs/zookeeperProgrammers.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/docs/zookeeperQuotas.pdf
----------------------------------------------------------------------
diff --git a/docs/zookeeperQuotas.pdf b/docs/zookeeperQuotas.pdf
index 2f67bb3..8a377d8 100644
Binary files a/docs/zookeeperQuotas.pdf and b/docs/zookeeperQuotas.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/docs/zookeeperReconfig.pdf
----------------------------------------------------------------------
diff --git a/docs/zookeeperReconfig.pdf b/docs/zookeeperReconfig.pdf
index 2462b5b..b8af567 100644
Binary files a/docs/zookeeperReconfig.pdf and b/docs/zookeeperReconfig.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/docs/zookeeperStarted.pdf
----------------------------------------------------------------------
diff --git a/docs/zookeeperStarted.pdf b/docs/zookeeperStarted.pdf
index 95a8383..4e8ae7e 100644
Binary files a/docs/zookeeperStarted.pdf and b/docs/zookeeperStarted.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/docs/zookeeperTutorial.pdf
----------------------------------------------------------------------
diff --git a/docs/zookeeperTutorial.pdf b/docs/zookeeperTutorial.pdf
index 0bf0226..4506d26 100644
Binary files a/docs/zookeeperTutorial.pdf and b/docs/zookeeperTutorial.pdf differ

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/src/contrib/monitoring/check_zookeeper.py
----------------------------------------------------------------------
diff --git a/src/contrib/monitoring/check_zookeeper.py b/src/contrib/monitoring/check_zookeeper.py
index b2f8db6..cff6a1f 100755
--- a/src/contrib/monitoring/check_zookeeper.py
+++ b/src/contrib/monitoring/check_zookeeper.py
@@ -293,7 +293,14 @@ class ZooKeeperServer(object):
                 result['zk_zxid_epoch']   = int(m.group(1), 16) >>32 # high 32 bits
                 continue
 
-        return result 
+            m = re.match('Proposal sizes last/min/max: (\d+)/(\d+)/(\d+)', line)
+            if m is not None:
+                result['zk_last_proposal_size'] = int(m.group(1))
+                result['zk_min_proposal_size'] = int(m.group(2))
+                result['zk_max_proposal_size'] = int(m.group(3))
+                continue
+
+        return result
 
     def _parse_line(self, line):
         try:

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/src/contrib/monitoring/ganglia/zookeeper.pyconf
----------------------------------------------------------------------
diff --git a/src/contrib/monitoring/ganglia/zookeeper.pyconf b/src/contrib/monitoring/ganglia/zookeeper.pyconf
index 179626f..44acd93 100644
--- a/src/contrib/monitoring/ganglia/zookeeper.pyconf
+++ b/src/contrib/monitoring/ganglia/zookeeper.pyconf
@@ -46,5 +46,8 @@ collection_group {
   metric { name = "zk_followers" }
   metric { name = "zk_synced_followers" }
   metric { name = "zk_pending_syncs" }
+  metric { name = "zk_last_proposal_size" }
+  metric { name = "zk_min_proposal_size" }
+  metric { name = "zk_max_proposal_size" }
 }
 

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/src/contrib/monitoring/ganglia/zookeeper_ganglia.py
----------------------------------------------------------------------
diff --git a/src/contrib/monitoring/ganglia/zookeeper_ganglia.py b/src/contrib/monitoring/ganglia/zookeeper_ganglia.py
index c72619f..bbb7a8e 100644
--- a/src/contrib/monitoring/ganglia/zookeeper_ganglia.py
+++ b/src/contrib/monitoring/ganglia/zookeeper_ganglia.py
@@ -214,7 +214,10 @@ def metric_init(params=None):
         'zk_max_file_descriptor_count': {'units': 'descriptors'},
         'zk_followers': {'units': 'nodes'},
         'zk_synced_followers': {'units': 'nodes'},
-        'zk_pending_syncs': {'units': 'syncs'}
+        'zk_pending_syncs': {'units': 'syncs'},
+        'zk_last_proposal_size': {'units': 'bytes'},
+        'zk_min_proposal_size': {'units': 'bytes'},
+        'zk_max_proposal_size': {'units': 'bytes'}
     }
     metric_handler.descriptors = {}
     for name, updates in metrics.iteritems():

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/src/java/main/org/apache/zookeeper/ClientCnxnSocket.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/ClientCnxnSocket.java b/src/java/main/org/apache/zookeeper/ClientCnxnSocket.java
index c2357cb..51ae8bf 100644
--- a/src/java/main/org/apache/zookeeper/ClientCnxnSocket.java
+++ b/src/java/main/org/apache/zookeeper/ClientCnxnSocket.java
@@ -115,7 +115,7 @@ abstract class ClientCnxnSocket {
         this.lastHeard = now;
     }
 
-    protected void readLength() throws IOException {
+    void readLength() throws IOException {
         int len = incomingBuffer.getInt();
         if (len < 0 || len >= packetLen) {
             throw new IOException("Packet len " + len + " is out of range!");

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/src/java/main/org/apache/zookeeper/server/NIOServerCnxn.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/NIOServerCnxn.java b/src/java/main/org/apache/zookeeper/server/NIOServerCnxn.java
index 446438c..14476e8 100644
--- a/src/java/main/org/apache/zookeeper/server/NIOServerCnxn.java
+++ b/src/java/main/org/apache/zookeeper/server/NIOServerCnxn.java
@@ -678,8 +678,6 @@ public class NIOServerCnxn extends ServerCnxn {
         }
     }
 
-    private final static byte fourBytes[] = new byte[4];
-
     /*
      * (non-Javadoc)
      *
@@ -689,23 +687,7 @@ public class NIOServerCnxn extends ServerCnxn {
     @Override
     public void sendResponse(ReplyHeader h, Record r, String tag) {
         try {
-            ByteArrayOutputStream baos = new ByteArrayOutputStream();
-            // Make space for length
-            BinaryOutputArchive bos = BinaryOutputArchive.getArchive(baos);
-            try {
-                baos.write(fourBytes);
-                bos.writeRecord(h, "header");
-                if (r != null) {
-                    bos.writeRecord(r, tag);
-                }
-                baos.close();
-            } catch (IOException e) {
-                LOG.error("Error serializing response");
-            }
-            byte b[] = baos.toByteArray();
-            ByteBuffer bb = ByteBuffer.wrap(b);
-            bb.putInt(b.length - 4).rewind();
-            sendBuffer(bb);
+            super.sendResponse(h, r, tag);
             if (h.getXid() > 0) {
                 // check throttling
                 if (outstandingRequests.decrementAndGet() < 1 ||

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/src/java/main/org/apache/zookeeper/server/NettyServerCnxn.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/NettyServerCnxn.java b/src/java/main/org/apache/zookeeper/server/NettyServerCnxn.java
index 9ff12e9..ec808a6 100644
--- a/src/java/main/org/apache/zookeeper/server/NettyServerCnxn.java
+++ b/src/java/main/org/apache/zookeeper/server/NettyServerCnxn.java
@@ -160,7 +160,6 @@ public class NettyServerCnxn extends ServerCnxn {
         }
     }
 
-    private static final byte[] fourBytes = new byte[4];
     static class ResumeMessageEvent implements MessageEvent {
         Channel channel;
         ResumeMessageEvent(Channel channel) {
@@ -182,23 +181,7 @@ public class NettyServerCnxn extends ServerCnxn {
         if (closingChannel || !channel.isOpen()) {
             return;
         }
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        // Make space for length
-        BinaryOutputArchive bos = BinaryOutputArchive.getArchive(baos);
-        try {
-            baos.write(fourBytes);
-            bos.writeRecord(h, "header");
-            if (r != null) {
-                bos.writeRecord(r, tag);
-            }
-            baos.close();
-        } catch (IOException e) {
-            LOG.error("Error serializing response");
-        }
-        byte b[] = baos.toByteArray();
-        ByteBuffer bb = ByteBuffer.wrap(b);
-        bb.putInt(b.length - 4).rewind();
-        sendBuffer(bb);
+        super.sendResponse(h, r, tag);
         if (h.getXid() > 0) {
             // zks cannot be null otherwise we would not have gotten here!
             if (!zkServer.shouldThrottle(outstandingCount.decrementAndGet())) {

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/src/java/main/org/apache/zookeeper/server/ServerCnxn.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/ServerCnxn.java b/src/java/main/org/apache/zookeeper/server/ServerCnxn.java
index f8a90cf..35d6c55 100644
--- a/src/java/main/org/apache/zookeeper/server/ServerCnxn.java
+++ b/src/java/main/org/apache/zookeeper/server/ServerCnxn.java
@@ -18,6 +18,7 @@
 
 package org.apache.zookeeper.server;
 
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -34,6 +35,7 @@ import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicLong;
 
+import org.apache.jute.BinaryOutputArchive;
 import org.apache.jute.Record;
 import org.apache.zookeeper.WatchedEvent;
 import org.apache.zookeeper.Watcher;
@@ -55,6 +57,8 @@ public abstract class ServerCnxn implements Stats, Watcher {
     
     private Set<Id> authInfo = Collections.newSetFromMap(new ConcurrentHashMap<Id, Boolean>());
 
+    private static final byte[] fourBytes = new byte[4];
+
     /**
      * If the client is of old version, we don't send r-o mode info to it.
      * The reason is that if we would, old C client doesn't read it, which
@@ -66,8 +70,26 @@ public abstract class ServerCnxn implements Stats, Watcher {
 
     abstract void close();
 
-    public abstract void sendResponse(ReplyHeader h, Record r, String tag)
-        throws IOException;
+    public void sendResponse(ReplyHeader h, Record r, String tag) throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        // Make space for length
+        BinaryOutputArchive bos = BinaryOutputArchive.getArchive(baos);
+        try {
+            baos.write(fourBytes);
+            bos.writeRecord(h, "header");
+            if (r != null) {
+                bos.writeRecord(r, tag);
+            }
+            baos.close();
+        } catch (IOException e) {
+            LOG.error("Error serializing response");
+        }
+        byte b[] = baos.toByteArray();
+        serverStats().updateClientResponseSize(b.length - 4);
+        ByteBuffer bb = ByteBuffer.wrap(b);
+        bb.putInt(b.length - 4).rewind();
+        sendBuffer(bb);
+    }
 
     /* notify the client the session is closing and close/cleanup socket */
     abstract void sendCloseSession();
@@ -133,12 +155,12 @@ public abstract class ServerCnxn implements Stats, Watcher {
         incrPacketsSent();
         ServerStats serverStats = serverStats();
         if (serverStats != null) {
-            serverStats().incrementPacketsSent();
+            serverStats.incrementPacketsSent();
         }
     }
 
     protected abstract ServerStats serverStats();
-    
+
     protected final Date established = new Date();
 
     protected final AtomicLong packetsReceived = new AtomicLong();

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/src/java/main/org/apache/zookeeper/server/ServerStats.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/ServerStats.java b/src/java/main/org/apache/zookeeper/server/ServerStats.java
index 3947d3a..87f37ad 100644
--- a/src/java/main/org/apache/zookeeper/server/ServerStats.java
+++ b/src/java/main/org/apache/zookeeper/server/ServerStats.java
@@ -21,6 +21,9 @@ package org.apache.zookeeper.server;
 
 
 import org.apache.zookeeper.common.Time;
+import org.apache.zookeeper.server.quorum.BufferStats;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.concurrent.atomic.AtomicLong;
 
@@ -28,6 +31,8 @@ import java.util.concurrent.atomic.AtomicLong;
  * Basic Server Statistics
  */
 public class ServerStats {
+    private static final Logger LOG = LoggerFactory.getLogger(ServerStats.class);
+
     private long packetsSent;
     private long packetsReceived;
     private long maxLatency;
@@ -36,6 +41,8 @@ public class ServerStats {
     private long count = 0;
     private AtomicLong fsyncThresholdExceedCount = new AtomicLong(0);
 
+    private final BufferStats clientResponseStats = new BufferStats();
+
     private final Provider provider;
 
     public interface Provider {
@@ -167,6 +174,14 @@ public class ServerStats {
     synchronized public void reset() {
         resetLatency();
         resetRequestCounters();
+        clientResponseStats.reset();
     }
 
+    public void updateClientResponseSize(int size) {
+        clientResponseStats.setLastBufferSize(size);
+    }
+
+    public BufferStats getClientResponseStats() {
+        return clientResponseStats;
+    }
 }

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/src/java/main/org/apache/zookeeper/server/ZooKeeperServerBean.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/ZooKeeperServerBean.java b/src/java/main/org/apache/zookeeper/server/ZooKeeperServerBean.java
index 43c3f6a..6ac7602 100644
--- a/src/java/main/org/apache/zookeeper/server/ZooKeeperServerBean.java
+++ b/src/java/main/org/apache/zookeeper/server/ZooKeeperServerBean.java
@@ -182,4 +182,19 @@ public class ZooKeeperServerBean implements ZooKeeperServerMXBean, ZKMBeanInfo {
     public int getJuteMaxBufferSize() {
         return BinaryInputArchive.maxBuffer;
     }
+
+    @Override
+    public int getLastClientResponseSize() {
+        return zks.serverStats().getClientResponseStats().getLastBufferSize();
+    }
+
+    @Override
+    public int getMinClientResponseSize() {
+        return zks.serverStats().getClientResponseStats().getMinBufferSize();
+    }
+
+    @Override
+    public int getMaxClientResponseSize() {
+        return zks.serverStats().getClientResponseStats().getMaxBufferSize();
+    }
 }

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/src/java/main/org/apache/zookeeper/server/ZooKeeperServerMXBean.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/ZooKeeperServerMXBean.java b/src/java/main/org/apache/zookeeper/server/ZooKeeperServerMXBean.java
index 5ff0991..d7e50d3 100644
--- a/src/java/main/org/apache/zookeeper/server/ZooKeeperServerMXBean.java
+++ b/src/java/main/org/apache/zookeeper/server/ZooKeeperServerMXBean.java
@@ -143,4 +143,19 @@ public interface ZooKeeperServerMXBean {
      * @return Returns the value of the following config setting: jute.maxbuffer
      */
     public int getJuteMaxBufferSize();
+
+    /**
+     * @return size of latest generated client response
+     */
+    public int getLastClientResponseSize();
+
+    /**
+     * @return size of smallest generated client response
+     */
+    public int getMinClientResponseSize();
+
+    /**
+     * @return size of largest generated client response
+     */
+    public int getMaxClientResponseSize();
 }

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/src/java/main/org/apache/zookeeper/server/admin/Commands.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/admin/Commands.java b/src/java/main/org/apache/zookeeper/server/admin/Commands.java
index fe160b9..4712261 100644
--- a/src/java/main/org/apache/zookeeper/server/admin/Commands.java
+++ b/src/java/main/org/apache/zookeeper/server/admin/Commands.java
@@ -330,12 +330,20 @@ public class Commands {
             response.put("open_file_descriptor_count", osMbean.getOpenFileDescriptorCount());
             response.put("max_file_descriptor_count", osMbean.getMaxFileDescriptorCount());
 
+            response.put("last_client_response_size", stats.getClientResponseStats().getLastBufferSize());
+            response.put("max_client_response_size", stats.getClientResponseStats().getMaxBufferSize());
+            response.put("min_client_response_size", stats.getClientResponseStats().getMinBufferSize());
+
             if (zkServer instanceof LeaderZooKeeperServer) {
                 Leader leader = ((LeaderZooKeeperServer) zkServer).getLeader();
 
                 response.put("followers", leader.getLearners().size());
                 response.put("synced_followers", leader.getForwardingFollowers().size());
                 response.put("pending_syncs", leader.getNumPendingSyncs());
+
+                response.put("last_proposal_size", leader.getProposalStats().getLastBufferSize());
+                response.put("max_proposal_size", leader.getProposalStats().getMaxBufferSize());
+                response.put("min_proposal_size", leader.getProposalStats().getMinBufferSize());
             }
 
             return response;
@@ -415,9 +423,13 @@ public class Commands {
             response.put("version", Version.getFullVersion());
             response.put("read_only", zkServer instanceof ReadOnlyZooKeeperServer);
             response.put("server_stats", zkServer.serverStats());
+            response.put("client_response", zkServer.serverStats().getClientResponseStats());
+            if (zkServer instanceof LeaderZooKeeperServer) {
+                Leader leader = ((LeaderZooKeeperServer)zkServer).getLeader();
+                response.put("proposal_stats", leader.getProposalStats());
+            }
             response.put("node_count", zkServer.getZKDatabase().getNodeCount());
             return response;
-
         }
     }
 

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/src/java/main/org/apache/zookeeper/server/command/MonitorCommand.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/command/MonitorCommand.java b/src/java/main/org/apache/zookeeper/server/command/MonitorCommand.java
index c32de4c..a17fe40 100644
--- a/src/java/main/org/apache/zookeeper/server/command/MonitorCommand.java
+++ b/src/java/main/org/apache/zookeeper/server/command/MonitorCommand.java
@@ -75,9 +75,9 @@ public class MonitorCommand extends AbstractFourLetterCommand {
             print("synced_followers", leader.getForwardingFollowers().size());
             print("pending_syncs", leader.getNumPendingSyncs());
 
-            print("last_proposal_size", leader.getProposalStats().getLastProposalSize());
-            print("max_proposal_size", leader.getProposalStats().getMaxProposalSize());
-            print("min_proposal_size", leader.getProposalStats().getMinProposalSize());
+            print("last_proposal_size", leader.getProposalStats().getLastBufferSize());
+            print("max_proposal_size", leader.getProposalStats().getMaxBufferSize());
+            print("min_proposal_size", leader.getProposalStats().getMinBufferSize());
         }
     }
 

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/src/java/main/org/apache/zookeeper/server/command/StatCommand.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/command/StatCommand.java b/src/java/main/org/apache/zookeeper/server/command/StatCommand.java
index d04f2f7..c6c4b87 100644
--- a/src/java/main/org/apache/zookeeper/server/command/StatCommand.java
+++ b/src/java/main/org/apache/zookeeper/server/command/StatCommand.java
@@ -25,7 +25,7 @@ import org.apache.zookeeper.server.ServerCnxn;
 import org.apache.zookeeper.server.ServerStats;
 import org.apache.zookeeper.server.quorum.Leader;
 import org.apache.zookeeper.server.quorum.LeaderZooKeeperServer;
-import org.apache.zookeeper.server.quorum.ProposalStats;
+import org.apache.zookeeper.server.quorum.BufferStats;
 import org.apache.zookeeper.server.quorum.ReadOnlyZooKeeperServer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -64,7 +64,7 @@ public class StatCommand extends AbstractFourLetterCommand {
             pw.println(zkServer.getZKDatabase().getNodeCount());
             if (serverStats.getServerState().equals("leader")) {
                 Leader leader = ((LeaderZooKeeperServer)zkServer).getLeader();
-                ProposalStats proposalStats = leader.getProposalStats();
+                BufferStats proposalStats = leader.getProposalStats();
                 pw.printf("Proposal sizes last/min/max: %s%n", proposalStats.toString());
             }
         }

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/src/java/main/org/apache/zookeeper/server/quorum/BufferStats.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/quorum/BufferStats.java b/src/java/main/org/apache/zookeeper/server/quorum/BufferStats.java
new file mode 100644
index 0000000..a76d80f
--- /dev/null
+++ b/src/java/main/org/apache/zookeeper/server/quorum/BufferStats.java
@@ -0,0 +1,89 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zookeeper.server.quorum;
+
+/**
+ * Provides live statistics about Jute buffer usage in term of proposal and client request size.
+ */
+public class BufferStats {
+    public static final int INIT_VALUE = -1;
+
+    /**
+     * Size of the last buffer usage.
+     */
+    private int lastBufferSize = INIT_VALUE;
+
+    /**
+     * Size of the smallest buffer usage.
+     */
+    private int minBufferSize = INIT_VALUE;
+
+    /**
+     * Size of the largest buffer usage.
+     */
+    private int maxBufferSize = INIT_VALUE;
+
+    /**
+     * Size of the last buffer usage.
+     */
+    public synchronized int getLastBufferSize() {
+        return lastBufferSize;
+    }
+
+    /**
+     * Updates statistics by setting the last buffer usage size.
+     */
+    public synchronized void setLastBufferSize(int value) {
+        lastBufferSize = value;
+        if (minBufferSize == INIT_VALUE || value < minBufferSize) {
+            minBufferSize = value;
+        }
+        if (value > maxBufferSize) {
+            maxBufferSize = value;
+        }
+    }
+
+    /**
+     * Size of the smallest buffer usage.
+     */
+    public synchronized int getMinBufferSize() {
+        return minBufferSize;
+    }
+
+    /**
+     * Size of the largest buffer usage.
+     */
+    public synchronized int getMaxBufferSize() {
+        return maxBufferSize;
+    }
+
+    /**
+     * Reset statistics.
+     */
+    public synchronized void reset() {
+        lastBufferSize = INIT_VALUE;
+        minBufferSize = INIT_VALUE;
+        maxBufferSize = INIT_VALUE;
+    }
+
+    @Override
+    public synchronized String toString() {
+        return String.format("%d/%d/%d", lastBufferSize, minBufferSize, maxBufferSize);
+    }
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/src/java/main/org/apache/zookeeper/server/quorum/Leader.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/quorum/Leader.java b/src/java/main/org/apache/zookeeper/server/quorum/Leader.java
index 4774a42..513500a 100644
--- a/src/java/main/org/apache/zookeeper/server/quorum/Leader.java
+++ b/src/java/main/org/apache/zookeeper/server/quorum/Leader.java
@@ -18,7 +18,6 @@
 
 package org.apache.zookeeper.server.quorum;
 
-import java.io.ByteArrayOutputStream;
 import java.io.BufferedInputStream;
 import java.io.IOException;
 import java.net.BindException;
@@ -42,7 +41,6 @@ import java.util.concurrent.ConcurrentMap;
 
 import javax.security.sasl.SaslException;
 
-import org.apache.jute.BinaryOutputArchive;
 import org.apache.zookeeper.ZooDefs.OpCode;
 import org.apache.zookeeper.common.Time;
 import org.apache.zookeeper.server.FinalRequestProcessor;
@@ -107,9 +105,9 @@ public class Leader {
     private final HashSet<LearnerHandler> learners =
         new HashSet<LearnerHandler>();
 
-    private final ProposalStats proposalStats;
+    private final BufferStats proposalStats;
 
-    public ProposalStats getProposalStats() {
+    public BufferStats getProposalStats() {
         return proposalStats;
     }
 
@@ -230,7 +228,7 @@ public class Leader {
 
     Leader(QuorumPeer self,LeaderZooKeeperServer zk) throws IOException {
         this.self = self;
-        this.proposalStats = new ProposalStats();
+        this.proposalStats = new BufferStats();
         try {
             if (self.getQuorumListenOnAllIPs()) {
                 ss = new ServerSocket(self.getQuorumAddress().getPort());
@@ -1061,7 +1059,7 @@ public class Leader {
         }
 
         byte[] data = SerializeUtils.serializeRequest(request);
-        proposalStats.setLastProposalSize(data.length);
+        proposalStats.setLastBufferSize(data.length);
         QuorumPacket pp = new QuorumPacket(Leader.PROPOSAL, request.zxid, data, null);
 
         Proposal p = new Proposal();

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/src/java/main/org/apache/zookeeper/server/quorum/LeaderBean.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/quorum/LeaderBean.java b/src/java/main/org/apache/zookeeper/server/quorum/LeaderBean.java
index 9f5eb24..4d4c856 100644
--- a/src/java/main/org/apache/zookeeper/server/quorum/LeaderBean.java
+++ b/src/java/main/org/apache/zookeeper/server/quorum/LeaderBean.java
@@ -55,17 +55,17 @@ public class LeaderBean extends ZooKeeperServerBean implements LeaderMXBean {
 
     @Override
     public int getLastProposalSize() {
-        return leader.getProposalStats().getLastProposalSize();
+        return leader.getProposalStats().getLastBufferSize();
     }
 
     @Override
     public int getMinProposalSize() {
-        return leader.getProposalStats().getMinProposalSize();
+        return leader.getProposalStats().getMinBufferSize();
     }
 
     @Override
     public int getMaxProposalSize() {
-        return leader.getProposalStats().getMaxProposalSize();
+        return leader.getProposalStats().getMaxBufferSize();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/src/java/main/org/apache/zookeeper/server/quorum/ProposalStats.java
----------------------------------------------------------------------
diff --git a/src/java/main/org/apache/zookeeper/server/quorum/ProposalStats.java b/src/java/main/org/apache/zookeeper/server/quorum/ProposalStats.java
deleted file mode 100644
index 2f3a9c7..0000000
--- a/src/java/main/org/apache/zookeeper/server/quorum/ProposalStats.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.zookeeper.server.quorum;
-
-/**
- * Provides live statistics about a running Leader.
- */
-public class ProposalStats {
-    /**
-     * Size of the last generated proposal. This should fit into server's jute.maxbuffer setting.
-     */
-    private int lastProposalSize = -1;
-
-    /**
-     * Size of the smallest proposal which has been generated since the server was started.
-     */
-    private int minProposalSize = -1;
-
-    /**
-     * Size of the largest proposal which has been generated since the server was started.
-     */
-    private int maxProposalSize = -1;
-
-    public synchronized int getLastProposalSize() {
-        return lastProposalSize;
-    }
-
-    synchronized void setLastProposalSize(int value) {
-        lastProposalSize = value;
-        if (minProposalSize == -1 || value < minProposalSize) {
-            minProposalSize = value;
-        }
-        if (value > maxProposalSize) {
-            maxProposalSize = value;
-        }
-    }
-
-    public synchronized int getMinProposalSize() {
-        return minProposalSize;
-    }
-
-    public synchronized int getMaxProposalSize() {
-        return maxProposalSize;
-    }
-
-    public synchronized void reset() {
-        lastProposalSize = -1;
-        minProposalSize = -1;
-        maxProposalSize = -1;
-    }
-
-    public synchronized String toString() {
-        return String.format("%d/%d/%d", lastProposalSize, minProposalSize, maxProposalSize);
-    }
-}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/src/java/test/org/apache/zookeeper/server/NIOServerCnxnTest.java
----------------------------------------------------------------------
diff --git a/src/java/test/org/apache/zookeeper/server/NIOServerCnxnTest.java b/src/java/test/org/apache/zookeeper/server/NIOServerCnxnTest.java
index 538c06a..4362b2c 100644
--- a/src/java/test/org/apache/zookeeper/server/NIOServerCnxnTest.java
+++ b/src/java/test/org/apache/zookeeper/server/NIOServerCnxnTest.java
@@ -24,12 +24,19 @@ import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.ZooDefs.Ids;
 import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.server.quorum.BufferStats;
 import org.apache.zookeeper.test.ClientBase;
 import org.junit.Assert;
 import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+
 public class NIOServerCnxnTest extends ClientBase {
     private static final Logger LOG = LoggerFactory
                         .getLogger(NIOServerCnxnTest.class);
@@ -47,7 +54,7 @@ public class NIOServerCnxnTest extends ClientBase {
             // make sure zkclient works
             zk.create(path, "test".getBytes(), Ids.OPEN_ACL_UNSAFE,
                     CreateMode.PERSISTENT);
-            Assert.assertNotNull("Didn't create znode:" + path,
+            assertNotNull("Didn't create znode:" + path,
                     zk.exists(path, false));
             // Defaults ServerCnxnFactory would be instantiated with
             // NIOServerCnxnFactory
@@ -68,5 +75,21 @@ public class NIOServerCnxnTest extends ClientBase {
         } finally {
             zk.close();
         }
+
+    }
+
+    @Test
+    public void testClientResponseStatsUpdate() throws IOException, InterruptedException, KeeperException {
+        try (ZooKeeper zk = createClient()) {
+            BufferStats clientResponseStats = serverFactory.getZooKeeperServer().serverStats().getClientResponseStats();
+            assertThat("Last client response size should be initialized with INIT_VALUE",
+                    clientResponseStats.getLastBufferSize(), equalTo(BufferStats.INIT_VALUE));
+
+            zk.create("/a", "test".getBytes(), Ids.OPEN_ACL_UNSAFE,
+                    CreateMode.PERSISTENT);
+
+            assertThat("Last client response size should be greater then zero after client request was performed",
+                    clientResponseStats.getLastBufferSize(), greaterThan(0));
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/src/java/test/org/apache/zookeeper/server/NettyServerCnxnTest.java
----------------------------------------------------------------------
diff --git a/src/java/test/org/apache/zookeeper/server/NettyServerCnxnTest.java b/src/java/test/org/apache/zookeeper/server/NettyServerCnxnTest.java
index 7d1b854..2038d8b 100644
--- a/src/java/test/org/apache/zookeeper/server/NettyServerCnxnTest.java
+++ b/src/java/test/org/apache/zookeeper/server/NettyServerCnxnTest.java
@@ -20,14 +20,22 @@ package org.apache.zookeeper.server;
 
 
 import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
 import org.apache.zookeeper.ZooDefs.Ids;
 import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.server.quorum.BufferStats;
 import org.apache.zookeeper.test.ClientBase;
 import org.junit.Assert;
 import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.IOException;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.junit.Assert.assertThat;
+
 /**
  * Test verifies the behavior of NettyServerCnxn which represents a connection
  * from a client to the server.
@@ -84,4 +92,19 @@ public class NettyServerCnxnTest extends ClientBase {
             zk.close();
         }
     }
+
+    @Test
+    public void testClientResponseStatsUpdate() throws IOException, InterruptedException, KeeperException {
+        try (ZooKeeper zk = createClient()) {
+            BufferStats clientResponseStats = serverFactory.getZooKeeperServer().serverStats().getClientResponseStats();
+            assertThat("Last client response size should be initialized with INIT_VALUE",
+                    clientResponseStats.getLastBufferSize(), equalTo(BufferStats.INIT_VALUE));
+
+            zk.create("/a", "test".getBytes(), Ids.OPEN_ACL_UNSAFE,
+                    CreateMode.PERSISTENT);
+
+            assertThat("Last client response size should be greater than 0 after client request was performed",
+                    clientResponseStats.getLastBufferSize(), greaterThan(0));
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/src/java/test/org/apache/zookeeper/server/admin/CommandsTest.java
----------------------------------------------------------------------
diff --git a/src/java/test/org/apache/zookeeper/server/admin/CommandsTest.java b/src/java/test/org/apache/zookeeper/server/admin/CommandsTest.java
index 47b86dd..aae788f 100644
--- a/src/java/test/org/apache/zookeeper/server/admin/CommandsTest.java
+++ b/src/java/test/org/apache/zookeeper/server/admin/CommandsTest.java
@@ -23,11 +23,13 @@ import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 import java.io.IOException;
+import java.nio.Buffer;
 import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.zookeeper.server.ServerStats;
 import org.apache.zookeeper.server.ZooKeeperServer;
+import org.apache.zookeeper.server.quorum.BufferStats;
 import org.apache.zookeeper.test.ClientBase;
 import org.junit.Test;
 
@@ -173,7 +175,10 @@ public class CommandsTest extends ClientBase {
                     new Field("ephemerals_count", Integer.class),
                     new Field("approximate_data_size", Long.class),
                     new Field("open_file_descriptor_count", Long.class),
-                    new Field("max_file_descriptor_count", Long.class));
+                    new Field("max_file_descriptor_count", Long.class),
+                    new Field("last_client_response_size", Integer.class),
+                    new Field("max_client_response_size", Integer.class),
+                    new Field("min_client_response_size", Integer.class));
     }
 
     @Test
@@ -187,7 +192,8 @@ public class CommandsTest extends ClientBase {
                 new Field("version", String.class),
                 new Field("read_only", Boolean.class),
                 new Field("server_stats", ServerStats.class),
-                new Field("node_count", Integer.class));
+                new Field("node_count", Integer.class),
+                new Field("client_response", BufferStats.class));
     }
 
     @Test
@@ -205,7 +211,8 @@ public class CommandsTest extends ClientBase {
                     new Field("read_only", Boolean.class),
                     new Field("server_stats", ServerStats.class),
                     new Field("node_count", Integer.class),
-                    new Field("connections", Iterable.class));
+                    new Field("connections", Iterable.class),
+                    new Field("client_response", BufferStats.class));
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/src/java/test/org/apache/zookeeper/server/quorum/BufferStatsTest.java
----------------------------------------------------------------------
diff --git a/src/java/test/org/apache/zookeeper/server/quorum/BufferStatsTest.java b/src/java/test/org/apache/zookeeper/server/quorum/BufferStatsTest.java
new file mode 100644
index 0000000..8435e85
--- /dev/null
+++ b/src/java/test/org/apache/zookeeper/server/quorum/BufferStatsTest.java
@@ -0,0 +1,58 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zookeeper.server.quorum;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class BufferStatsTest {
+    @Test
+    public void testSetProposalSizeSetMinMax() {
+        BufferStats stats = new BufferStats();
+        assertEquals(-1, stats.getLastBufferSize());
+        assertEquals(-1, stats.getMinBufferSize());
+        assertEquals(-1, stats.getMaxBufferSize());
+        stats.setLastBufferSize(10);
+        assertEquals(10, stats.getLastBufferSize());
+        assertEquals(10, stats.getMinBufferSize());
+        assertEquals(10, stats.getMaxBufferSize());
+        stats.setLastBufferSize(20);
+        assertEquals(20, stats.getLastBufferSize());
+        assertEquals(10, stats.getMinBufferSize());
+        assertEquals(20, stats.getMaxBufferSize());
+        stats.setLastBufferSize(5);
+        assertEquals(5, stats.getLastBufferSize());
+        assertEquals(5, stats.getMinBufferSize());
+        assertEquals(20, stats.getMaxBufferSize());
+    }
+
+    @Test
+    public void testReset() {
+        BufferStats stats = new BufferStats();
+        stats.setLastBufferSize(10);
+        assertEquals(10, stats.getLastBufferSize());
+        assertEquals(10, stats.getMinBufferSize());
+        assertEquals(10, stats.getMaxBufferSize());
+        stats.reset();
+        assertEquals(-1, stats.getLastBufferSize());
+        assertEquals(-1, stats.getMinBufferSize());
+        assertEquals(-1, stats.getMaxBufferSize());
+    }
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/src/java/test/org/apache/zookeeper/server/quorum/ProposalStatsTest.java
----------------------------------------------------------------------
diff --git a/src/java/test/org/apache/zookeeper/server/quorum/ProposalStatsTest.java b/src/java/test/org/apache/zookeeper/server/quorum/ProposalStatsTest.java
deleted file mode 100644
index 1f71979..0000000
--- a/src/java/test/org/apache/zookeeper/server/quorum/ProposalStatsTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.zookeeper.server.quorum;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class ProposalStatsTest {
-    @Test
-    public void testSetProposalSizeSetMinMax() {
-        ProposalStats stats = new ProposalStats();
-        assertEquals(-1, stats.getLastProposalSize());
-        assertEquals(-1, stats.getMinProposalSize());
-        assertEquals(-1, stats.getMaxProposalSize());
-        stats.setLastProposalSize(10);
-        assertEquals(10, stats.getLastProposalSize());
-        assertEquals(10, stats.getMinProposalSize());
-        assertEquals(10, stats.getMaxProposalSize());
-        stats.setLastProposalSize(20);
-        assertEquals(20, stats.getLastProposalSize());
-        assertEquals(10, stats.getMinProposalSize());
-        assertEquals(20, stats.getMaxProposalSize());
-        stats.setLastProposalSize(5);
-        assertEquals(5, stats.getLastProposalSize());
-        assertEquals(5, stats.getMinProposalSize());
-        assertEquals(20, stats.getMaxProposalSize());
-    }
-
-    @Test
-    public void testReset() {
-        ProposalStats stats = new ProposalStats();
-        stats.setLastProposalSize(10);
-        assertEquals(10, stats.getLastProposalSize());
-        assertEquals(10, stats.getMinProposalSize());
-        assertEquals(10, stats.getMaxProposalSize());
-        stats.reset();
-        assertEquals(-1, stats.getLastProposalSize());
-        assertEquals(-1, stats.getMinProposalSize());
-        assertEquals(-1, stats.getMaxProposalSize());
-    }
-}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/src/java/test/org/apache/zookeeper/server/quorum/StatCommandTest.java
----------------------------------------------------------------------
diff --git a/src/java/test/org/apache/zookeeper/server/quorum/StatCommandTest.java b/src/java/test/org/apache/zookeeper/server/quorum/StatCommandTest.java
index 0328b7a..eccb6b1 100644
--- a/src/java/test/org/apache/zookeeper/server/quorum/StatCommandTest.java
+++ b/src/java/test/org/apache/zookeeper/server/quorum/StatCommandTest.java
@@ -27,7 +27,6 @@ import org.apache.zookeeper.server.command.StatCommand;
 import org.junit.Before;
 import org.junit.Test;
 
-import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.ArrayList;
@@ -44,7 +43,7 @@ public class StatCommandTest {
     private ServerStats.Provider providerMock;
 
     @Before
-    public void setUp() throws IOException {
+    public void setUp() {
         outputWriter = new StringWriter();
         ServerCnxn serverCnxnMock = mock(ServerCnxn.class);
 
@@ -55,7 +54,7 @@ public class StatCommandTest {
         ZKDatabase zkDatabaseMock = mock(ZKDatabase.class);
         when(zks.getZKDatabase()).thenReturn(zkDatabaseMock);
         Leader leaderMock = mock(Leader.class);
-        when(leaderMock.getProposalStats()).thenReturn(new ProposalStats());
+        when(leaderMock.getProposalStats()).thenReturn(new BufferStats());
         when(zks.getLeader()).thenReturn(leaderMock);
 
         ServerCnxnFactory serverCnxnFactory = mock(ServerCnxnFactory.class);

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/src/java/test/org/apache/zookeeper/server/quorum/StatResetCommandTest.java
----------------------------------------------------------------------
diff --git a/src/java/test/org/apache/zookeeper/server/quorum/StatResetCommandTest.java b/src/java/test/org/apache/zookeeper/server/quorum/StatResetCommandTest.java
index ddaf831..0c20c58 100644
--- a/src/java/test/org/apache/zookeeper/server/quorum/StatResetCommandTest.java
+++ b/src/java/test/org/apache/zookeeper/server/quorum/StatResetCommandTest.java
@@ -96,8 +96,8 @@ public class StatResetCommandTest {
 
         when(serverStats.getServerState()).thenReturn("leader");
 
-        ProposalStats proposalStats = mock(ProposalStats.class);
-        when(leader.getProposalStats()).thenReturn(proposalStats);
+        BufferStats bufferStats = mock(BufferStats.class);
+        when(leader.getProposalStats()).thenReturn(bufferStats);
 
         // Act
         statResetCommand.commandRun();
@@ -106,6 +106,6 @@ public class StatResetCommandTest {
         String output = outputWriter.toString();
         assertEquals("Server stats reset.\n", output);
         verify(serverStats, times(1)).reset();
-        verify(proposalStats, times(1)).reset();
+        verify(bufferStats, times(1)).reset();
     }
 }

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/328b9de0/zookeeper-docs/src/documentation/content/xdocs/zookeeperAdmin.xml
----------------------------------------------------------------------
diff --git a/zookeeper-docs/src/documentation/content/xdocs/zookeeperAdmin.xml b/zookeeper-docs/src/documentation/content/xdocs/zookeeperAdmin.xml
index 62edb2a..c9cb884 100644
--- a/zookeeper-docs/src/documentation/content/xdocs/zookeeperAdmin.xml
+++ b/zookeeper-docs/src/documentation/content/xdocs/zookeeperAdmin.xml
@@ -1933,6 +1933,9 @@ server.3=zoo3:2888:3888</programlisting>
               zk_pending_syncs    0               - only exposed by the Leader
               zk_open_file_descriptor_count 23    - only available on Unix platforms
               zk_max_file_descriptor_count 1024   - only available on Unix platforms
+              zk_last_proposal_size 23
+              zk_min_proposal_size 23
+              zk_max_proposal_size 64
               </programlisting>
 
               <para>The output is compatible with java properties format and the content 


Mime
View raw message