diff options
Diffstat (limited to 'modules/jmx')
-rw-r--r-- | modules/jmx/pom.xml | 26 | ||||
-rw-r--r-- | modules/jmx/src/main/clojure/clojure/contrib/jmx.clj | 121 | ||||
-rw-r--r-- | modules/jmx/src/main/clojure/clojure/contrib/jmx/Bean.clj | 35 |
3 files changed, 182 insertions, 0 deletions
diff --git a/modules/jmx/pom.xml b/modules/jmx/pom.xml new file mode 100644 index 00000000..70d24b3f --- /dev/null +++ b/modules/jmx/pom.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http//www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 + http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.clojure.contrib</groupId> + <artifactId>parent</artifactId> + <version>1.3.0-SNAPSHOT</version> + <relativePath>../parent</relativePath> + </parent> + <artifactId>jmx</artifactId> + <dependencies> + <dependency> + <groupId>org.clojure.contrib</groupId> + <artifactId>def</artifactId> + <version>1.3.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.clojure.contrib</groupId> + <artifactId>string</artifactId> + <version>1.3.0-SNAPSHOT</version> + </dependency> + </dependencies> +</project>
\ No newline at end of file diff --git a/modules/jmx/src/main/clojure/clojure/contrib/jmx.clj b/modules/jmx/src/main/clojure/clojure/contrib/jmx.clj new file mode 100644 index 00000000..ca0232ed --- /dev/null +++ b/modules/jmx/src/main/clojure/clojure/contrib/jmx.clj @@ -0,0 +1,121 @@ +;; Copyright (c) Stuart Halloway, 2009. All rights reserved. The use +;; and distribution terms for this software are covered by the Eclipse +;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) +;; which can be found in the file epl-v10.html at the root of this +;; distribution. By using this software in any fashion, you are +;; agreeing to be bound by the terms of this license. You must not +;; remove this notice, or any other, from this software. + + +(ns ^{:author "Stuart Halloway" + :doc "JMX support for Clojure + + Requires post-Clojure 1.0 git edge for clojure.test, clojure.backtrace. + This is prerelease. + This API will change. + Send reports to stu@thinkrelevance.com. + + Usage + (require '[clojure.contrib.jmx :as jmx]) + + What beans do I have? + + (jmx/mbean-names \"*:*\") + -> #<HashSet [java.lang:type=MemoryPool,name=CMS Old Gen, + java.lang:type=Memory, ...] + + What attributes does a bean have? + + (jmx/attribute-names \"java.lang:type=Memory\") + -> (:Verbose :ObjectPendingFinalizationCount + :HeapMemoryUsage :NonHeapMemoryUsage) + + What is the value of an attribute? + + (jmx/read \"java.lang:type=Memory\" :ObjectPendingFinalizationCount) + -> 0 + + Can't I just have *all* the attributes in a Clojure map? + + (jmx/mbean \"java.lang:type=Memory\") + -> {:NonHeapMemoryUsage + {:used 16674024, :max 138412032, :init 24317952, :committed 24317952}, + :HeapMemoryUsage + {:used 18619064, :max 85393408, :init 0, :committed 83230720}, + :ObjectPendingFinalizationCount 0, + :Verbose false} + + Can I find and invoke an operation? + + (jmx/operation-names \"java.lang:type=Memory\") + -> (:gc) + (jmx/invoke \"java.lang:type=Memory\" :gc) + -> nil + + What about some other process? Just run *any* of the above code + inside a with-connection: + + (jmx/with-connection {:host \"localhost\", :port 3000} + (jmx/mbean \"java.lang:type=Memory\")) + -> {:ObjectPendingFinalizationCount 0, + :HeapMemoryUsage ... etc.} + + Can I serve my own beans? Sure, just drop a Clojure ref + into an instance of clojure.contrib.jmx.Bean, and the bean + will expose read-only attributes for every key/value pair + in the ref: + + (jmx/register-mbean + (Bean. + (ref {:string-attribute \"a-string\"})) + \"my.namespace:name=Value\")"} + clojure.contrib.jmx + (:refer-clojure :exclude [read]) + (:use clojure.contrib.def + [clojure.contrib.string :only [as-str]] + [clojure.stacktrace :only (root-cause)] + [clojure.walk :only [postwalk]]) + (:import [clojure.lang Associative] + java.lang.management.ManagementFactory + [javax.management Attribute DynamicMBean MBeanInfo ObjectName RuntimeMBeanException MBeanAttributeInfo] + [javax.management.remote JMXConnectorFactory JMXServiceURL])) + +(defvar *connection* (ManagementFactory/getPlatformMBeanServer) + "The connection to be used for JMX ops. Defaults to the local process.") + +(load "jmx/data") +(load "jmx/client") +(load "jmx/server") + +(defn mbean-names + "Finds all MBeans matching a name on the current *connection*." + [n] + (.queryNames *connection* (as-object-name n) nil)) + +(defn attribute-names + "All attribute names available on an MBean." + [n] + (doall (map #(-> % .getName keyword) + (.getAttributes (mbean-info n))))) + +(defn operation-names + "All operation names available on an MBean." + [n] + (doall (map #(-> % .getName keyword) (operations n)))) + +(defn invoke [n op & args] + (if ( seq args) + (.invoke *connection* (as-object-name n) (as-str op) + (into-array args) + (into-array String (op-param-types n op))) + (.invoke *connection* (as-object-name n) (as-str op) + nil nil))) + +(defn mbean + "Like clojure.core/bean, but for JMX beans. Returns a read-only map of + a JMX bean's attributes. If an attribute it not supported, value is + set to the exception thrown." + [n] + (into {} (map (fn [attr-name] [(keyword attr-name) (read-supported n attr-name)]) + (attribute-names n)))) + diff --git a/modules/jmx/src/main/clojure/clojure/contrib/jmx/Bean.clj b/modules/jmx/src/main/clojure/clojure/contrib/jmx/Bean.clj new file mode 100644 index 00000000..cae67d21 --- /dev/null +++ b/modules/jmx/src/main/clojure/clojure/contrib/jmx/Bean.clj @@ -0,0 +1,35 @@ +(ns clojure.contrib.jmx.Bean + (:gen-class + :implements [javax.management.DynamicMBean] + :init init + :state state + :constructors {[Object] []}) + (:require [clojure.contrib.jmx :as jmx]) + (:import [javax.management DynamicMBean MBeanInfo AttributeList])) + +(defn -init [derefable] + [[] derefable]) + +; TODO: rest of the arguments, as needed +(defn generate-mbean-info [clj-bean] + (MBeanInfo. (.. clj-bean getClass getName) ; class name + "Clojure Dynamic MBean" ; description + (jmx/map->attribute-infos @(.state clj-bean)) ; attributes + nil ; constructors + nil ; operations + nil)) ; notifications + +(defn -getMBeanInfo + [this] + (generate-mbean-info this)) + +(defn -getAttribute + [this attr] + (@(.state this) (keyword attr))) + +(defn -getAttributes + [this attrs] + (let [result (AttributeList.)] + (doseq [attr attrs] + (.add result (.getAttribute this attr))) + result))
\ No newline at end of file |