2008年 2月 25日 月曜日 |
JRubyでJMX English Translation: (Yahoo!) / (Google) ずいぶん前の話ですが、IdMセミナーより: Identity ManagerをJMXで監視するというエントリでJMXによるアプリケーションサーバ監視をJRubyからやる。というのをご紹介しました。そのときに、JRuby開発者Thomas Eneboにこんなモジュールを作ってもらいました。ずっと前から紹介しようと思っていたのに、今頃気づきました・・・。すいません・・・。
include Java
import javax.management.DynamicMBean
import javax.management.MBeanInfo
import javax.management.ObjectName
import javax.management.remote.JMXServiceURL
import javax.management.remote.JMXConnectorServerFactory
module JMX
class MBeanServerConnector
def initialize(location, server)
@url = JMXServiceURL.new location
@server = JMXConnectorServerFactory.newJMXConnectorServer @url, nil, server.server
if block_given?
start; yield; stop
end
end
def active?; @server.isActive; end
def start; @server.start; end
def stop; @server.stop if active?; end
end
# Represents both MBeanServer and MBeanServerConnection
class MBeanServer
import javax.management.remote.JMXConnectorFactory
import javax.management.MBeanServerFactory
import javax.management.Attribute
attr_accessor :server
@@classes = {}
def initialize(location=nil, username=nil, password=nil)
if (location)
url = JMXServiceURL.new location
if (username)
credentials = java.lang.String[2].new
credentials[0], credentials[1] = username, password
env = {"jmx.remote.credentials" => credentials}
else
env = nil
end
@server =JMXConnectorFactory.connect(url, env).getMBeanServerConnection
else
@server = MBeanServerFactory.createMBeanServer
end
end
def get_mbean(object_name)
name = ObjectName.new object_name
raise NoSuchBeanError.new("No name: #{object_name}") unless @server.isRegistered(name)
@server.getObjectInstance name
generate_proxy(name)
end
def create_mbean(class_name, object_name)
name = ObjectName.new object_name
@server.createMBean class_name, name, nil, nil
generate_proxy(name)
end
def default_domain; @server.getDefaultDomain; end
def domains; @server.domains; end
def mbean_count; @server.getMBeanCount; end
def query_names(name=nil, query=nil)
name = ObjectName.new name
@server.queryNames(name, query)
end
def register_mbean(object, object_name)
name = ObjectName.new object_name
@server.registerMBean(object, name)
generate_proxy(name)
end
def generate_proxy(object_name)
info = @server.getMBeanInfo object_name
class_name = info.className
return @@classes[class_name].new if @@classes[class_name]
# Make local so closure capturage.
server = @server
proxy = Class.new
# Attributes are supported using aref/aset syntax
proxy.class_eval do
define_method(:[]) do |name|
server.getAttribute object_name, name
end
define_method(:[]=) do |name, value|
server.setAttribute object_name, Attribute.new(attr.name, value)
end
end
# Operations get method names (collision potential)
info.operations.each do |op| proxy.class_eval do
define_method(op.name) do |*args|
args_array = JMX::MBeanServer.args_array(args)
signature_array = JMX::MBeanServer.signature_array(args_array)
server.invoke object_name, op.name, args_array, signature_array
end
end
end
# Add notification listener methods
proxy.class_eval do
define_method(:add_notification_listener) do |listener,*rest|
filter, handback = *rest
server.addNotificationListener object_name, listener, filter, handback
end
define_method(:remove_notification_listener) do |listener|
server.removeNotificationListener object_name, listener
end
define_method(:method_missing) do |method_name, *args|
args_array = JMX::MBeanServer.args_array(args)
signature_array = JMX::MBeanServer.signature_array(args_array)
server.invoke object_name, method_name.to_s, args_array, signature_array
end
end
@@classes[info.className] = proxy
proxy.new
end
class << self
def args_array(params)
return nil if params.nil?
array = java.lang.String[params.length].new
params.each_with_index { |parm, i| array[i] = parm }
array
end
def signature_array(params)
return nil if params.nil?
array = java.lang.String[params.length].new
params.each_with_index do |parm, i| array[i] = Java.ruby_to_java(parm).java_class.name
end
array
end
end
end
class NoSuchBeanError < RuntimeError
end
end
class RubyDynamicMBean import DynamicMBean
def initialize(name, description)
@info = MBeanInfo.new name, description, nil, nil, nil, nil
@name, @description = name, description
end
def getAttribute(attribute); $stderr.puts "getAttribute"; end
def getAttributes(attributes); $stderr.puts "getAttributes"; end
def getMBeanInfo; $stderr.puts "getMBeanInfo"; @info; end
def invoke(actionName, params=nil, signature=nil); send(actionName, *params)
end
def setAttribute(attribute); $stderr.puts "setAttribute"; end
def setAttributes(attributes); $stderr.puts "setAttributes"; end
def to_s; "#@name: #@description"; end
def inspect; "#@name: #@description"; end
def toString; "#@name: #@description"; end
end
これを使うと、JRubyからJMXを使うときにこんな感じでプログラムを書けます。
require 'jmx'
username = "admin"
password = "adminadmin"
url = "service:jmx:rmi:///jndi/rmi://localhost:8686/jmxrmi"
server = JMX::MBeanServer.new url, username, password
listener = server.get_mbean "com.sun.appserv:name=server,type=virtual-server,category=monitor,server=server"
puts "Server started at: #{Time.new(listener["hosts-starttime"])}"
こんな感じで、ほんの数行。JMXの手続きとかは知らなくても大丈夫。
投稿されたコメント:
★ お名前を空欄にするとIPアドレスが、お名前欄に記入されます。
|
Today's Page Hits: 84 |