Hey folks, I needed a way to keep track of individual ZK instances' memory usage without using JMX, so I went and added a new four letter word: memo
Example usage: # echo memo | nc 127.0.0.1 44011 Maximum memory: 514850816 Free memory: 479290568 Total memory: 514850816 This exposes the same data that ZOOKEEPER-716 logs, basically the runtime's maximum/free/total memory. Attached patch is against branch-3.4.13 as that's the version we're currently using. Any feedback is highly appreciated. Should I go ahead and create a PR/Jira issue? Thanks, - Bram
diff --git a/src/docs/src/documentation/content/xdocs/zookeeperAdmin.xml b/src/docs/src/documentation/content/xdocs/zookeeperAdmin.xml index d88ddbdb..858448d4 100644 --- a/src/docs/src/documentation/content/xdocs/zookeeperAdmin.xml +++ b/src/docs/src/documentation/content/xdocs/zookeeperAdmin.xml @@ -1180,6 +1180,14 @@ server.3=zoo3:2888:3888</programlisting> </listitem> </varlistentry> + <varlistentry> + <term>memo</term> + + <listitem> + <para>Gets server memory usage information.</para> + </listitem> + </varlistentry> + <varlistentry> <term>gtmk</term> diff --git a/src/java/main/org/apache/zookeeper/server/NIOServerCnxn.java b/src/java/main/org/apache/zookeeper/server/NIOServerCnxn.java index 24cc7b46..b922c407 100644 --- a/src/java/main/org/apache/zookeeper/server/NIOServerCnxn.java +++ b/src/java/main/org/apache/zookeeper/server/NIOServerCnxn.java @@ -850,6 +850,29 @@ public void commandRun() { } } + /** + * The memo command prints basic memory usage information (in bytes): + * - The JVM's max memory (Xmx) + * - The current free memory + * - The totally allocated memory + */ + private class MemoCommand extends CommandThread { + public MemoCommand(PrintWriter pw) { + super(pw); + } + + @Override + public void commandRun() { + final Runtime runtime = Runtime.getRuntime(); + pw.print("Maximum memory: "); + pw.println(runtime.maxMemory()); + pw.print("Free memory: "); + pw.println(runtime.freeMemory()); + pw.print("Total memory: "); + pw.println(runtime.totalMemory()); + } + } + private class NopCommand extends CommandThread { private String msg; @@ -969,6 +992,10 @@ private boolean checkFourLetterWord(final SelectionKey k, final int len) IsroCommand isro = new IsroCommand(pwriter); isro.start(); return true; + } else if (len == memoCmd) { + MemoCommand memo = new MemoCommand(pwriter); + memo.start(); + return true; } return false; } diff --git a/src/java/main/org/apache/zookeeper/server/NettyServerCnxn.java b/src/java/main/org/apache/zookeeper/server/NettyServerCnxn.java index 271fc19e..428e9a85 100644 --- a/src/java/main/org/apache/zookeeper/server/NettyServerCnxn.java +++ b/src/java/main/org/apache/zookeeper/server/NettyServerCnxn.java @@ -630,6 +630,29 @@ public void commandRun() { } } + /** + * The memo command prints basic memory usage information (in bytes): + * - The JVM's max memory (Xmx) + * - The current free memory + * - The totally allocated memory + */ + private class MemoCommand extends CommandThread { + public MemoCommand(PrintWriter pw) { + super(pw); + } + + @Override + public void commandRun() { + final Runtime runtime = Runtime.getRuntime(); + pw.print("Maximum memory: "); + pw.println(runtime.maxMemory()); + pw.print("Free memory: "); + pw.println(runtime.freeMemory()); + pw.print("Total memory: "); + pw.println(runtime.totalMemory()); + } + } + private class NopCommand extends CommandThread { private String msg; @@ -728,6 +751,10 @@ private boolean checkFourLetterWord(final Channel channel, IsroCommand isro = new IsroCommand(pwriter); isro.start(); return true; + } else if (len == memoCmd) { + MemoCommand memo = new MemoCommand(pwriter); + memo.start(); + return true; } return false; } diff --git a/src/java/main/org/apache/zookeeper/server/ServerCnxn.java b/src/java/main/org/apache/zookeeper/server/ServerCnxn.java index dfa1d74e..95968ba2 100644 --- a/src/java/main/org/apache/zookeeper/server/ServerCnxn.java +++ b/src/java/main/org/apache/zookeeper/server/ServerCnxn.java @@ -240,6 +240,13 @@ public String toString() { protected final static int isroCmd = ByteBuffer.wrap("isro".getBytes()) .getInt(); + /* + * See <a href="{@docRoot}/../../../docs/zookeeperAdmin.html#sc_zkCommands"> + * Zk Admin</a>. this link is for all the commands. + */ + protected final static int memoCmd = ByteBuffer.wrap("memo".getBytes()) + .getInt(); + final static Map<Integer, String> cmd2String = new HashMap<Integer, String>(); private static final String ZOOKEEPER_4LW_COMMANDS_WHITELIST = "zookeeper.4lw.commands.whitelist"; @@ -344,6 +351,7 @@ public synchronized static boolean isEnabled(String command) { cmd2String.put(wchsCmd, "wchs"); cmd2String.put(mntrCmd, "mntr"); cmd2String.put(isroCmd, "isro"); + cmd2String.put(memoCmd, "memo"); } protected void packetReceived() { diff --git a/src/java/test/org/apache/zookeeper/test/FourLetterWordsTest.java b/src/java/test/org/apache/zookeeper/test/FourLetterWordsTest.java index bc8d0713..4f054082 100644 --- a/src/java/test/org/apache/zookeeper/test/FourLetterWordsTest.java +++ b/src/java/test/org/apache/zookeeper/test/FourLetterWordsTest.java @@ -106,6 +106,10 @@ public void testFourLetterWords() throws Exception { verify("mntr", "fsync_threshold_exceed_count"); verify("stat", "Connections"); verify("srvr", "Connections"); + + verify("memo", "Free memory"); + verify("memo", "Total memory"); + verify("memo", "Maximum memory"); } private String sendRequest(String cmd) throws IOException {