You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kafka.apache.org by jk...@apache.org on 2011/10/24 20:52:12 UTC
svn commit: r1188288 -
/incubator/kafka/trunk/core/src/main/scala/kafka/tools/JmxTool.scala
Author: jkreps
Date: Mon Oct 24 18:52:12 2011
New Revision: 1188288
URL: http://svn.apache.org/viewvc?rev=1188288&view=rev
Log:
KAFKA-166 Add JMX perf tool.
Added:
incubator/kafka/trunk/core/src/main/scala/kafka/tools/JmxTool.scala
Added: incubator/kafka/trunk/core/src/main/scala/kafka/tools/JmxTool.scala
URL: http://svn.apache.org/viewvc/incubator/kafka/trunk/core/src/main/scala/kafka/tools/JmxTool.scala?rev=1188288&view=auto
==============================================================================
--- incubator/kafka/trunk/core/src/main/scala/kafka/tools/JmxTool.scala (added)
+++ incubator/kafka/trunk/core/src/main/scala/kafka/tools/JmxTool.scala Mon Oct 24 18:52:12 2011
@@ -0,0 +1,110 @@
+/*
+ * 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 kafka.tools
+
+import java.util.Date
+import java.text.SimpleDateFormat
+import javax.management._
+import javax.management.remote._
+import joptsimple.{OptionSet, OptionParser}
+import scala.collection.JavaConversions._
+import scala.collection.mutable
+import scala.math._
+
+
+object JmxTool {
+
+ def main(args: Array[String]) {
+ // Parse command line
+ val parser = new OptionParser
+ val objectNameOpt =
+ parser.accepts("object-name", "A JMX object name to use as a query. This can contain wild cards, and this option " +
+ "can be given multiple times to specify more than one query. If no objects are specified " +
+ "all objects will be queried.")
+ .withRequiredArg
+ .describedAs("name")
+ .ofType(classOf[String])
+ val reportingIntervalOpt = parser.accepts("reporting-interval", "Interval in MS with which to poll jmx stats.")
+ .withRequiredArg
+ .describedAs("ms")
+ .ofType(classOf[java.lang.Integer])
+ .defaultsTo(5000)
+ val helpOpt = parser.accepts("help", "Print usage information.")
+ val dateFormatOpt = parser.accepts("date-format", "The date format to use for formatting the time field. " +
+ "See java.text.SimpleDateFormat for options.")
+ .withRequiredArg
+ .describedAs("format")
+ .ofType(classOf[String])
+ .defaultsTo("yyyy-MM-dd HH:mm:ss.SSS")
+ val jmxServiceUrlOpt =
+ parser.accepts("jmx-url", "The url to connect to to poll JMX data. See Oracle javadoc for JMXServiceURL for details.")
+ .withRequiredArg
+ .describedAs("service-url")
+ .ofType(classOf[String])
+ .defaultsTo("service:jmx:rmi:///jndi/rmi://:9999/jmxrmi")
+
+ val options = parser.parse(args : _*)
+
+ if(options.has(helpOpt)) {
+ parser.printHelpOn(System.out)
+ System.exit(0)
+ }
+
+ val url = new JMXServiceURL(options.valueOf(jmxServiceUrlOpt))
+ val interval = options.valueOf(reportingIntervalOpt).intValue
+ val dateFormat = new SimpleDateFormat(options.valueOf(dateFormatOpt))
+ val jmxc = JMXConnectorFactory.connect(url, null)
+ val mbsc = jmxc.getMBeanServerConnection()
+
+ val queries: Iterable[ObjectName] =
+ if(options.has(objectNameOpt))
+ options.valuesOf(objectNameOpt).map(new ObjectName(_))
+ else
+ List(null)
+ val names = queries.map((name: ObjectName) => asSet(mbsc.queryNames(name, null))).flatten
+ val attributes: Iterable[(ObjectName, Array[String])] =
+ names.map((name: ObjectName) => (name, mbsc.getMBeanInfo(name).getAttributes().map(_.getName)))
+
+ // print csv header
+ val keys = List("time") ++ queryAttributes(mbsc, names).keys.toArray.sorted
+ println(keys.map("\"" + _ + "\"").mkString(", "))
+
+ while(true) {
+ val start = System.currentTimeMillis
+ val attributes = queryAttributes(mbsc, names)
+ attributes("time") = dateFormat.format(new Date)
+ println(keys.map(attributes(_)).mkString(", "))
+ val sleep = max(0, interval - (System.currentTimeMillis - start))
+ Thread.sleep(sleep)
+ }
+ }
+
+ def queryAttributes(mbsc: MBeanServerConnection, names: Iterable[ObjectName]) = {
+ var attributes = new mutable.HashMap[String, Any]()
+ for(name <- names) {
+ val mbean = mbsc.getMBeanInfo(name)
+ for(attrObj <- mbsc.getAttributes(name, mbean.getAttributes.map(_.getName))) {
+ val attr = attrObj.asInstanceOf[Attribute]
+ attributes(name + ":" + attr.getName) = attr.getValue
+ }
+ }
+ attributes
+ }
+
+}
\ No newline at end of file