Thursday, 17 February 2011

JRuby Script to Monitor a Oracle WebLogic GridLink Data Source Remotely

In WebLogic 10.3.4 release, a single data source implementation has been introduced to support Oracle RAC cluster. To simplify and consolidate its support for Oracle RAC, WebLogic Server has provided a single data source that is enhanced to support the capabilities of Oracle RAC.  It provides a single connection pool/data source within Oracle WebLogic Server that supports the consumption of database services in an unrestricted manner. For more information on this see the URL below.

http://download.oracle.com/docs/cd/E17904_01/web.1111/e13737/gridlink_datasources.htm

In the example below we show how we can monitor this new Active GridLink Data Source from a JRuby script to get runtime information as the Data Source is in use from the MBean. In this example we are assuming our Data Source has a name "jdbc/gridlinkDS" which was created in the console of WebLogic itself.

1. Determine the remote connection URL to connect to WebLogic 10.3.4. The URL will be something as follows which shows are are connecting to the runtime MBean server of the managed server itself. In short this will be where you have targeted your GridLink Data Source to, it's not the ADMIN SERVER it's the managed server itself.

Format:

service:jmx:iiop://{hostname}:{managed-server-port}/jndi/weblogic.management.mbeanservers.runtime

Example:

service:jmx:iiop://wayne-p2.au.oracle.com:7003/jndi/weblogic.management.mbeanservers.runtime

2. At this point it's worth connecting using JConsole remotely to the WebLogic server using the URL above as this will help you see how the MBeans are structured and what you then need to alter the JRuby script with. Start jconsole ensuring your using wlfullclient.jar in the classpath from $WLS_HOME/server/lib directory.

Windows Example: (Connecting to a remote linux x86 server)

> jconsole -J-Djava.class.path=C:\jdev\weblogic-client\1034\wlfullclient.jar;C:\jdev\jdk\jdk1.6.0_21\lib\jconsole.jar -J-Djmx.remote.protocol.provider.pkgs=weblogic.management.remote

3. Connect using the service url from #1 above and with your username/password for the managed server where the GridLink Data Source is targeted for.



4. Click on the "MBeans" tab

5. At this point we want to determine what the MBean for the GridLink Data Source is but also what the MBean names are for the instances within the RAC cluster. To do that click on "com.bea" using the + symbol to expand the tree.

6. Scroll down and locate your GridLink Data Source in this case it's "jdbc/gridlinkDS" , use the + symbol to expand the tree

7. Click on the + symbol next to "JDBCOracleDataSourceRuntime"

8. Now actually click on "JDBCOracleDataSourceRuntime" to reveal the MBean name for the actual GidLink Data Source. Make a note of it which is displayed in the field "Object Name" in the right hand side of the dialog.

com.bea:ServerRuntime=apple,Name=jdbc/gridlinkDS,Type=JDBCOracleDataSourceRuntime

9. Select the "Attributes" node in the tree to view the GridLink Data Source runtime attributes.

10. Double click on the "Instances" Value field to reveal the MBean names for the individual instances within your cluster. Make a note of them as we will need them shortly. For my example there as follows.

com.bea:ServerRuntime=apple,Name=A11,Type=JDBCOracleDataSourceInstanceRuntime,JDBCOracleDataSourceRuntime=jdbc/gridlinkDS
com.bea:ServerRuntime=apple,Name=A12,Type=JDBCOracleDataSourceInstanceRuntime,JDBCOracleDataSourceRuntime=jdbc/gridlinkDS

11. Create a test client as follows
require 'java'
require 'rubygems'
require 'jmx4r'
require 'C:/jdev/weblogic-client/1034/wlfullclient.jar'

java_import 'javax.management.ObjectName'
java_import java.lang.System

class MonitorGridLinkDataSource
  def initialize(user, passwd, url)
    System.setProperty("jmx.remote.protocol.provider.pkgs", "weblogic.management.remote")
    @user, @passwd, @url = user, passwd, url
       
    @conn = JMX::MBean.establish_connection :url => @url, :username => @user, :password => @passwd 
  end

  # add getters and setters for all attrributes we wish to expose    
  attr_reader :user, :passwd, :url, :conn
  
  def display_array (value)
    data = "" 
    value.each do |x|
      data += "\n\t" + x.to_s
    end
    return data
  end

  def display_attribute_data(conn, object_name, attribute)  
    s = conn.get_attribute object_name, attribute
    search_str = s.to_s
    if (/^\[Ljava.lang.String/.match(search_str)) or 
       (/^\[I/.match(search_str)) or
       (/^\[Ljavax.management.ObjectName/.match(search_str))
      # we have a array with data
      return display_array s
    else
      return search_str
    end 
  end
  
  def to_s    
    "MonitorGridLinkDataSource [user=#{@user}, passwd=#{@passwd}, " +    
    "url=#{@url}]"    
  end  
  
  def run(parent_ds_runtime_mbean_name, child_ds_instances)

    mbean = JMX::MBean.find_by_name parent_ds_runtime_mbean_name
    object_name = ObjectName.new parent_ds_runtime_mbean_name

    #
    # Display main JDBC grindlink Data Source MBean info
    # 
    printf "\n** JDBC GridLink Data Source mbean \"jdbc/gridlinkDS\" ** \n\n"

    # display attributes key/values
    mbean.attributes.each do |key, value|  
     puts "Name: #{value}, Value: #{display_attribute_data conn, object_name, value}\n"
    end

    #
    # Now display info about each RAC instances within the gridlink DS
    #
    # Note: there will be as many instances as your RAC cluster contains here, in my case 
    # just a 2 node RAC cluster here

    child_ds_instances.each {|mbean_name| 
      ds1_mbean = JMX::MBean.find_by_name mbean_name
      object_name1 = ObjectName.new mbean_name
      
      printf "\n** Instance MBean \n\t[#{mbean_name}] \n\n"
      ds1_mbean.attributes.each do |key, value|  
       puts "Name: #{value}, Value: #{display_attribute_data conn, object_name1, value}\n"
      end
    }
    
  end

end

print "Run at ", Time.now , "\n"

#Connection details to MBeanServer within Weblogic 10.3.4 
url = "service:jmx:iiop://wayne-p2.au.oracle.com:7003/jndi/weblogic.management.mbeanservers.runtime"
username = "weblogic"
password = "welcome1"

# parent GridLink Data Source MBean name
parent_ds_runtime_mbean_name = 
      "com.bea:ServerRuntime=apple,Name=jdbc/gridlinkDS,Type=JDBCOracleDataSourceRuntime"
      
# child instance MBean array, add for each instance in the RAC cluster
child_ds_instances = 
  ["com.bea:ServerRuntime=apple,Name=A11,Type=JDBCOracleDataSourceInstanceRuntime,JDBCOracleDataSourceRuntime=jdbc/gridlinkDS", 
   "com.bea:ServerRuntime=apple,Name=A12,Type=JDBCOracleDataSourceInstanceRuntime,JDBCOracleDataSourceRuntime=jdbc/gridlinkDS"]

begin
  mon_grid_link_ds = MonitorGridLinkDataSource.new username, password, url
  puts mon_grid_link_ds
  while (true)
    mon_grid_link_ds.run parent_ds_runtime_mbean_name, child_ds_instances
    # sleep for 20 seconds
    puts "\nSleeping for 20 seconds....\n"   
    sleep 20
  end
rescue 
  print "\n** Error occured **\n"
 print "Failed executing GridLink Data Source Monitoring from JRuby ", $!, "\n"  
end

print "\nEnded at ", Time.now , "\n" 

12. Edit the following lines as per the information we collected above.

require 'C:/jdev/weblogic-client/1034/wlfullclient.jar'
...

#Connection details to MBeanServer within Weblogic 10.3.4 
url = "service:jmx:iiop://wayne-p2.au.oracle.com:7003/jndi/weblogic.management.mbeanservers.runtime"
username = "weblogic"
password = "welcome1"

# parent GridLink Data Source MBean name
parent_ds_runtime_mbean_name = 
      "com.bea:ServerRuntime=apple,Name=jdbc/gridlinkDS,Type=JDBCOracleDataSourceRuntime"
      
# child instance MBean array, add for each instance in the RAC cluster
child_ds_instances = 
["com.bea:ServerRuntime=apple,Name=A11,Type=JDBCOracleDataSourceInstanceRuntime,JDBCOracleDataSourceRuntime=jdbc/gridlinkDS", 
 "com.bea:ServerRuntime=apple,Name=A12,Type=JDBCOracleDataSourceInstanceRuntime,JDBCOracleDataSourceRuntime=jdbc/gridlinkDS"]

...



Note: We previously installed "jmx4r" ruby gem to allow us to use JMX API to communicate with the WebLogic server as follows


> jruby -S gem install jmx4r

13. Run the JRuby script as follows it will continually run sleeping every 20 seconds to display runtime information regarding your GridLink Data Source. To end it simply use CNRL-C to stop it running.

> jruby gridlink-monitor.rb

Output

Run at Thu Feb 17 21:55:32 +1100 2011
MonitorGridLinkDataSource [user=weblogic, passwd=welcome1, url=service:jmx:iiop://wayne-p2.au.oracle.com:7003/jndi/weblogic.management.mbean
servers.runtime]


** JDBC GridLink Data Source mbean "jdbc/gridlinkDS" **


Name: ActiveConnectionsCurrentCount, Value: 0
Name: WaitingForConnectionFailureTotal, Value: 0
Name: Instances, Value:
        com.bea:ServerRuntime=apple,Name=A11,Type=JDBCOracleDataSourceInstanceRuntime,JDBCOracleDataSourceRuntime=jdbc/gridlinkDS
        com.bea:ServerRuntime=apple,Name=A12,Type=JDBCOracleDataSourceInstanceRuntime,JDBCOracleDataSourceRuntime=jdbc/gridlinkDS
Name: FailedRCLBBasedBorrowCount, Value: 0
Name: WaitingForConnectionTotal, Value: 0
Name: ConnectionsTotalCount, Value: 28
Name: SuccessfulRCLBBasedBorrowCount, Value: 0
Name: DriverVersion, Value: 11.2.0.2.0
Name: WaitingForConnectionCurrentCount, Value: 0
Name: LeakedConnectionCount, Value: 0
Name: HighestNumUnavailable, Value: 20
Name: PrepStmtCacheAccessCount, Value: 0
Name: LastTask, Value:
Name: Parent, Value: com.bea:Name=apple,Type=ServerRuntime
Name: WaitSecondsHighCount, Value: 0
Name: ActiveConnectionsHighCount, Value: 20
Name: FailedAffinityBasedBorrowCount, Value: 0
Name: PrepStmtCacheHitCount, Value: 0
Name: ActiveConnectionsAverageCount, Value: 0
Name: VersionJDBCDriver, Value: oracle.jdbc.OracleDriver
Name: DatabaseProductVersion, Value: Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Data Mining and Real Application Testing options
Name: SuccessfulAffinityBasedBorrowCount, Value: 0
Name: PrepStmtCacheDeleteCount, Value: 0
Name: ReserveRequestCount, Value: 36
Name: FailuresToReconnectCount, Value: 0
Name: WaitingForConnectionHighCount, Value: 0
Name: PrepStmtCacheMissCount, Value: 0
Name: Enabled, Value: true
Name: FailedReserveRequestCount, Value: 0
Name: Type, Value: JDBCOracleDataSourceRuntime
Name: HighestNumAvailable, Value: 20
Name: WorkManagerRuntimes, Value:
Name: DatabaseProductName, Value: Oracle
Name: ONSClientRuntime, Value: com.bea:ServerRuntime=apple,Name=jdbc/gridlinkDS,Type=ONSClientRuntime,JDBCOracleDataSourceRuntime=jdbc/gridl
inkDS
Name: Properties, Value: {user=scott}
Name: CurrCapacityHighCount, Value: 20
Name: PrepStmtCacheCurrentSize, Value: 0
Name: ServiceName, Value:
Name: JDBCDriverRuntime, Value:
Name: WaitingForConnectionSuccessTotal, Value: 0
Name: NumUnavailable, Value: 0
Name: PrepStmtCacheAddCount, Value: 0
Name: DriverName, Value: Oracle JDBC driver
Name: NumAvailable, Value: 20
Name: ModuleId, Value: jdbc/gridlinkDS
Name: Name, Value: jdbc/gridlinkDS
Name: State, Value: Running
Name: ConnectionDelayTime, Value: 133
Name: DeploymentState, Value: 2
Name: CurrCapacity, Value: 20


** Instance MBean
        [com.bea:ServerRuntime=apple,Name=A11,Type=JDBCOracleDataSourceInstanceRuntime,JDBCOracleDataSourceRuntime=jdbc/gridlinkDS]


Name: Parent, Value: com.bea:ServerRuntime=apple,Name=jdbc/gridlinkDS,Type=JDBCOracleDataSourceRuntime
Name: Enabled, Value: true
Name: ActiveConnectionsCurrentCount, Value: 0
Name: Type, Value: JDBCOracleDataSourceInstanceRuntime
Name: NumAvailable, Value: 10
Name: Signature, Value: instance=A11,service=pas_srv,database=A1,host=auw2k3
Name: CurrentWeight, Value: 1
Name: Name, Value: A11
Name: ConnectionsTotalCount, Value: 14
Name: ReserveRequestCount, Value: 19
Name: State, Value: Enabled
Name: NumUnavailable, Value: 0
Name: CurrCapacity, Value: 10
Name: InstanceName, Value: A11


** Instance MBean
        [com.bea:ServerRuntime=apple,Name=A12,Type=JDBCOracleDataSourceInstanceRuntime,JDBCOracleDataSourceRuntime=jdbc/gridlinkDS]


Name: Parent, Value: com.bea:ServerRuntime=apple,Name=jdbc/gridlinkDS,Type=JDBCOracleDataSourceRuntime
Name: Enabled, Value: true
Name: ActiveConnectionsCurrentCount, Value: 0
Name: Type, Value: JDBCOracleDataSourceInstanceRuntime
Name: NumAvailable, Value: 10
Name: Signature, Value: instance=A12,service=pas_srv,database=A1,host=auw2k4
Name: CurrentWeight, Value: 1
Name: Name, Value: A12
Name: ConnectionsTotalCount, Value: 14
Name: ReserveRequestCount, Value: 17
Name: State, Value: Enabled
Name: NumUnavailable, Value: 0
Name: CurrCapacity, Value: 10
Name: InstanceName, Value: A12


Sleeping for 20 seconds....

1 comment:

Anonymous said...

hi, good site very much appreciatted