Configuring and Using the WebLogic Diagnostic Framework
You can use the WebLogic Server Administration Console to enable, configure, and monitor features of WebLogic Server, including the WebLogic Diagnostic Framework (WLDF). You can do the same tasks programmatically using the JMX API and the WebLogic Scripting Tool (WLST).
In addition to the information provided in the following sections, use the information in the following manuals to develop and deploy applications, and to use WLST:
The WLDF framework consists of several components. If you conceptualize the flow of data in terms of data generation and data retrieval:
In general, server input configuration is primarily an administrative task, accomplished either through the console or through WLST scripts. Deployable descriptor modules, XML configuration files, are the primary method for configuring diagnostic resources at both the system level (servers and clusters) and at the application level. (For information on configuring WLDF resources, see Understanding WLDF Configuration.)
Output retrieval via the Accessor component can be either an administrative or a programmatic task.
When you create WLDF resources using the Administration Console or WLST, WebLogic Server creates MBeans, managed beans, for each resource. You can then access these MBeans using JMX or the WebLogic Scripting Tool (WLST). Because weblogic.WLST
is a JMX client; any task you can perform using WLST you can also perform programmatically through JMX.
Table 12-1 lists the beans and packages associated with WLDF and its components. Figure 12-1 groups the beans by type.
Package: |
|
Package: |
|
Figure 12-1 WLDF Configuration MBeans, Runtime MBeans, and System Module Beans
The WebLogic Diagnostic Framework enables you to perform the following tasks programmatically:
The configuration and runtime APIs configure and monitor WLDF. Both the configuration and the runtime APIs are exposed as MBeans.
You can use the APIs to configure, activate, and deactivate data collection; to configure watches, notifications, alarms, and diagnostic image captures; and to access data.
This section covers the following topics:
The Configuration APIs define interfaces that are used to configure the following WLDF components:
Note: The configuration APIs do not support configuration of application-level instrumentation. However, configuration changes for application-level instrumentation can be effected using Java Specification Request (JSR) 88 APIs.
The runtime APIs define interfaces that are used to monitor the runtime state of the WLDF components. Instances of these APIs are instantiated on instances of individual managed servers. These APIs are defined as runtime MBeans so JMX clients can easily access them.
The Runtime APIs encapsulate all other runtime interfaces for the individual WLDF components. These APIs are included in the weblogic.management.runtime
package.
You can use the runtime APIs to monitor the following WLDF components:
The following two packages are provided:
weblogic.diagnostics.context
contains:DiagnosticContextConstants
, which defines the indices of dye flags supported by the WebLogic diagnostics system.DiagnosticConDtextHelper
, which provides applications limited access to the diagnostic context.weblogic.diagnostics.watch
contains:
WLDF configurations are stored in XML descriptor files that conform to the WebLogic Server schema weblogic-diagnostics.xsd
. The schema is available at the following URL:
http://www.bea.com/ns/weblogic/90/diagnostics.xsd
See WebLogic Server Diagnostics Configuration Schema Reference for documentation.
You create and manage WLDF resources either as system modules or as application modules, similar to standard J2EE modules.
A WLDF application module can be deployed as a stand-alone resource, in which case the resource is available to the servers or cluster targeted during the deployment process, or as part of an enterprise application. An application module deployed as part of an enterprise application is available only to the enclosing application (an application-scoped resource). Using application-scoped resources ensures that an application always has access to required resources, and simplifies the process of deploying the application into new environments.
In contrast to system modules, application modules are owned by the developer who created and packaged the module, rather than the administrator who deploys the module. This means that the administrator has more limited control over WLDF application modules. When deploying an application module, an administrator can change resource properties that were specified in the module, but cannot add or delete resources.
Application modules can be deployed, or undeployed, using JSR-88 interfaces, and updated by a deployment plan.
Table 12-2 compares the function and scope of system and application modules.
For detailed information on creating modules and deploying applications, see Deploying Applications to WebLogic Server.
The following examples use WLDF beans and packages to access and modify information on a running server:
In addition, see the WLST and JMX examples in WebLogic Scripting Tool Examples.
The following example uses the DiagnosticContextHelper
class from the weblogic.diagnostics.context
package to get and set the value of the DYE_0 flag. (For information on diagnostic contexts, see Configuring the Diagnostic Context.)
To compile and run the program:
javac -d . DiagnosticContextExample.java
This will create the ./weblogic/diagnostics/examples
directory and populate it with DiagnosticContextExample.class
.
java weblogic.diagnostics.examples.DiagnosticContextExample
Listing 12-1 Example: DiagnosticContextExample.java
package weblogic.diagnostics.examples;
import weblogic.diagnostics.context.DiagnosticContextHelper;
public class DiagnosticContextExample {
public static void main(String args[]) throws Exception {
System.out.println("ContextId=" +
DiagnosticContextHelper.getContextId());
System.out.println("isDyedWith(DYE_0)=" +
DiagnosticContextHelper.isDyedWith(DiagnosticContextHelper.DYE_0));
DiagnosticContextHelper.setDye(DiagnosticContextHelper.DYE_0, true);
System.out.println("isDyedWith(DYE_0)=" +
DiagnosticContextHelper.isDyedWith(DiagnosticContextHelper.DYE_0));
}
}
The HarvesterMonitor
program uses the Harvester JMX notification to identify when a harvest cycle has occurred. It then retrieves the new values using the Accessor. All access is performed through JMX. This section includes a description of notification listeners followed by the HarvesterMonitor.java
code:
For information on the Harvester component, see Configuring the Harvester for Metric Collection.
Notification listeners provide an appropriate implementation for a particular transport medium. For example, SMTP notification listeners provide the mechanism to establish an SMTP connection with a mail server and trigger an e-mail with the notification instance that it receives. JMX, SNMP, JMS and other types of listeners provide their respective implementations as well.
Note: You can develop plug-ins that propagate events generated by the WebLogic Diagnostic Framework using transport mediums other than SMTP, JMX, SNMP, or JMS. One approach is to use the JMX NotificationListener
interface to implement an object, and then propagate the notification according to the requirements of the selected transport medium.
Table 12-3 describes each notification listener type that is provided with WebLogic Server and the relevant configuration settings for each type.
By default, all notifications fired from watch rules are stored in the server log file in addition to being fired through the configured medium.
To compile and run the HarvesterMonitor
program:
javac -d . HarvesterMonitor.java
This will create the ./weblogic/diagnostics/examples
directory and populate it with HarvesterMonitor.class
and HarvesterMonitor$HarvestCycleHandler.class
.
java HarvesterMonitor <server> <port> <uname> <pw> [<types>]
You will need access to a WebLogic Server instance, and will need to know the server's name, port number, administrator's login name, and the administrator's password.
You can provide an optional list of harvested type names. If provided, the program will display only the values for those types. However, for each selected type, the monitor displays the complete set of collected values; there is no way to constrain the values displayed for a selected type.
Only values that are explicitly configured for harvesting are displayed. Values collected solely to support watch rules (implicit values) are not displayed.
The following command requires that '.' is in the CLASSPATH variable, and that you run the command from the directory where you compiled the program. The command connects to the myserver
server, at port 7001
, as user weblogic
, with a password of weblogic
:
java weblogic.diagnostics.examples.HarvesterMonitor myserver 7001
weblogic weblogic
See Listing 12-3 for an example of output from the HarvesterMonitor.
Listing 12-2 Example: HarvesterMonitor.java
package weblogic.diagnostics.examples;
import weblogic.management.mbeanservers.runtime.RuntimeServiceMBean;
import javax.management.*;
import javax.management.remote.*;
import javax.naming.Context;
import java.util.*;
public class HarvesterMonitor {
private static String accessorRuntimeMBeanName;
private static ObjectName accessorRuntimeMBeanObjectName;
private static String harvRuntimeMBeanName;
private static ObjectName harvRuntimeMBeanObjectName;
private static MBeanServerConnection rmbs;
private static ObjectName getObjectName(String objectNameStr) {
try { return new ObjectName(getCanonicalName(objectNameStr)); }
catch (RuntimeException x) { throw x; }
catch (Exception x) { x.printStackTrace(); throw new
RuntimeException(x); }
}
private static String getCanonicalName(String objectNameStr) {
try { return new ObjectName(objectNameStr).getCanonicalName(); }
catch (RuntimeException x) { throw x; }
catch (Exception x) { x.printStackTrace(); throw new
RuntimeException(x); }
}
private static String serverName;
private static int port;
private static String userName;
private static String password;
private static ArrayList typesToMonitor = null;
public static void main(String[] args) throws Exception {
if (args.length < 4) {
System.out.println(
"Usage: java weblogic.diagnostics.harvester.HarvesterMonitor " +
"<serverName> <port> <userName> <password> [<types>]" +
weblogic.utils.PlatformConstants.EOL +
" where <types> (optional) is a comma-separated list " +
"of types to monitor.");
System.exit(1);
}
serverName = args[0];
port = Integer.parseInt(args[1]);
userName = args[2];
password = args[3];
accessorRuntimeMBeanName = getCanonicalName(
"com.bea:ServerRuntime=" + serverName + ",Name=HarvestedDataArchive,Type=WLDFDataAccessRuntime" + ",WLDFAccessRuntime=Accessor,WLDFRuntime=WLDFRuntime");
accessorRuntimeMBeanObjectName =
getObjectName(accessorRuntimeMBeanName);
harvRuntimeMBeanName = getCanonicalName(
"com.bea:ServerRuntime=" + serverName +
",Name=WLDFHarvesterRuntime,Type=WLDFHarvesterRuntime" +
",WLDFRuntime=WLDFRuntime");
harvRuntimeMBeanObjectName = getObjectName(harvRuntimeMBeanName);
if (args.length > 4) {
String typesStr = args[4];
typesToMonitor = new ArrayList();
int index;
while ((index = typesStr.indexOf(",")) > 0) {
String typeName = typesStr.substring(0,index).trim();
typesToMonitor.add(typeName);
typesStr = typesStr.substring(index+1);
}
typesToMonitor.add(typesStr.trim());
}
rmbs = getRuntimeMBeanServerConnection();
new HarvesterMonitor().new HarvestCycleHandler();
while(true) {Thread.sleep(100000);}
}
static protected String JNDI = "/jndi/";
static public MBeanServerConnection getRuntimeMBeanServerConnection()
throws Exception {
JMXServiceURL serviceURL;
serviceURL =
new JMXServiceURL("t3",
"localhost",
port,
JNDI + RuntimeServiceMBean.MBEANSERVER_JNDI_NAME);
System.out.println("ServerName=" + serverName);
System.out.println("URL=" + serviceURL);
Hashtable h = new Hashtable();
h.put(Context.SECURITY_PRINCIPAL, userName);
h.put(Context.SECURITY_CREDENTIALS, password);
h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES,
"weblogic.management.remote");
JMXConnector connector = JMXConnectorFactory.connect(serviceURL,h);
return connector.getMBeanServerConnection();
}
class HarvestCycleHandler implements NotificationListener {
// used to track harvest cycles
private int timestampIndex;
private int domainIndex;
private int serverIndex;
private int typeIndex;
private int instNameIndex;
private int attrNameIndex;
private int attrTypeIndex;
private int attrValueIndex;
long lastSampleTime = System.currentTimeMillis();
HarvestCycleHandler() throws Exception{
System.out.println("Harvester monitor started...");
try {
setUpRecordIndices();
rmbs.addNotificationListener(harvRuntimeMBeanObjectName,
this, null, null);
}
catch (javax.management.InstanceNotFoundException x) {
System.out.println("Cannot find JMX data. " +
"Is the server name correct?");
System.exit(1);
}
}
private void setUpRecordIndices() throws Exception {
Map columnIndexMap = (Map)rmbs.getAttribute(
accessorRuntimeMBeanObjectName, "ColumnIndexMap");
timestampIndex = ((Integer)columnIndexMap.get("TIMESTAMP")).intValue();
domainIndex =
((Integer)columnIndexMap.get("DOMAIN")).intValue();
serverIndex =
((Integer)columnIndexMap.get("SERVER")).intValue();
typeIndex =
((Integer)columnIndexMap.get("TYPE")).intValue();
instNameIndex =
((Integer)columnIndexMap.get("NAME")).intValue();
attrNameIndex =
((Integer)columnIndexMap.get("ATTRNAME")).intValue();
attrTypeIndex =
((Integer)columnIndexMap.get("ATTRTYPE")).intValue();
attrValueIndex = ((Integer)columnIndexMap.get("ATTRVALUE")).intValue();
}
public synchronized void handleNotification(Notification notification,
Object handback) {
System.out.println("\n------------------------------------------");
long thisSampleTime = System.currentTimeMillis()+1;
try {
String lastTypeName = null;
String lastInstName = null;
String cursor = (String)rmbs.invoke(accessorRuntimeMBeanObjectName,
"openCursor",
new Object[]{new Long(lastSampleTime),
new Long(thisSampleTime), null},
new String[]{ "java.lang.Long",
"java.lang.Long", "java.lang.String" } );
while (((Boolean)rmbs.invoke(accessorRuntimeMBeanObjectName,
"hasMoreData",
new Object[]{cursor},
new String[]{"java.lang.String"})).booleanValue()) {
Object[] os = (Object[])rmbs.invoke(accessorRuntimeMBeanObjectName,
"fetch",
new Object[]{cursor},
new String[]{"java.lang.String"});
for (int i = 0; i < os.length; i++) {
Object[] values = (Object[])os[i];
String typeName = (String)values[typeIndex];
String instName = (String)values[instNameIndex];
String attrName = (String)values[attrNameIndex];
if (!typeName.equals(lastTypeName)) {
if (typesToMonitor != null &&
!typesToMonitor.contains(typeName)) continue;
System.out.println("\nType " + typeName);
lastTypeName = typeName;
}
if (!instName.equals(lastInstName)) {
System.out.println("\n Instance " + instName);
lastInstName = instName;
}
Object attrValue = values[attrValueIndex];
System.out.println(" - " + attrName + "=" + attrValue);
}
}
lastSampleTime = thisSampleTime;
}
catch (Exception e) {e.printStackTrace();}
}
}
}
Listing 12-3 contains sample output from the HarvesterMonitor program:
Listing 12-3 Sample Output from HarvesterMonitor
ServerName=myserver
URL=service:jmx:t3://localhost:7001/jndi/weblogic.management.mbeanservers.runtime
Harvester monitor started...
------------------------------------------------------
Type weblogic.management.runtime.WLDFHarvesterRuntimeMBean
Instance com.bea:Name=WLDFHarvesterRuntime,ServerRuntime=myserver,Type=WLDFHarvesterRuntime,WLDFRuntime=WLDFRuntime
- TotalSamplingTime=202048863
- CurrentSnapshotElapsedTime=1839619
Type weblogic.management.runtime.ServerRuntimeMBean
Instance com.bea:Name=myserver,Type=ServerRuntime
- RestartRequired=false
- ListenPortEnabled=true
- ActivationTime=1118319317071
- ServerStartupTime=40671
- ServerClasspath= [deleted long classpath listing]
- CurrentMachine=
- SocketsOpenedTotalCount=1
- State=RUNNING
- RestartsTotalCount=0
- AdminServer=true
- AdminServerListenPort=7001
- ClusterMaster=false
- StateVal=2
- CurrentDirectory=C:\testdomain\.
- AdminServerHost=10.40.8.123
- OpenSocketsCurrentCount=1
- ShuttingDown=false
- SSLListenPortEnabled=false
- AdministrationPortEnabled=false
- AdminServerListenPortSecure=false
- Registered=true
The following example program uses JMX to print log entries to standard out. All access is performed through JMX. (For information on the Accessor component, see Accessing Diagnostic Data Using the Data Accessor.)
To compile and run the program:
javac -d . JMXAccessorExample.java
This will create the ./weblogic/diagnostics/examples
directory and populate it with JMXAccessorExample.class
.
java weblogic.diagnostics.example.JMXAccessor <logicalName> <query>
You will need access to a WebLogic Server instance, and will need to know the server's name, port number, administrator's login name, and the administrator's password.
The logicalName
is the name of the log. Valid names are: HarvestedDataArchive
, EventsDataArchive
, ServerLog
, DomainLog
, HTTPAccessLog
, ServletAccessorHelper.WEBAPP_LOG, RAUtil.CONNECTOR_LOG,
JMSMessageLog,
and CUSTOM
.
The query
is constructed using the syntax described in WLDF Query Language. For the JMXAccessorExample
program, an empty query
(an empty pair of double quotation marks, ""
) returns all entries in the log.
The following command requires that '.' is in the CLASSPATH variable, and that you run the command from the directory where you compiled the program. The program uses the IIOP (Internet Inter-ORB Protocol) protocol to connect to port 7001
, as user weblogic
, with a password of weblogic
, and prints all entries in the ServerLog to standard out:
java weblogic.diagnostics.examples.JMXAccessorExample ServerLog ""
You can modify the example to use a username/password combination for your site.
Listing 12-4 JMXAccessorExample.java
package weblogic.diagnostics.examples;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Hashtable;
import java.util.Iterator;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import javax.naming.Context;
public class JMXAccessorExample {
private static final String JNDI = "/jndi/";
public static void main(String[] args) {
try {
if (args.length != 2) {
System.err.println("Incorrect invocation. Correct usage is:\n" +
"java weblogic.diagnostics.examples.JMXAccessorExample " +
"<logicalName> <query>");
System.exit(1);
}
String logicalName = args[0];
String query = args[1];
MBeanServerConnection mbeanServerConnection =
lookupMBeanServerConnection();
ObjectName service = new
ObjectName(weblogic.management.mbeanservers.runtime.RuntimeServiceMBean.OBJECT_NAME);
ObjectName serverRuntime =
(ObjectName) mbeanServerConnection.getAttribute(service,
"ServerRuntime");
ObjectName wldfRuntime =
(ObjectName) mbeanServerConnection.getAttribute(serverRuntime,
"WLDFRuntime");
ObjectName wldfAccessRuntime =
(ObjectName) mbeanServerConnection.getAttribute(wldfRuntime,
"WLDFAccessRuntime");
ObjectName wldfDataAccessRuntime =
(ObjectName) mbeanServerConnection.invoke(wldfAccessRuntime,
"lookupWLDFDataAccessRuntime", new Object[] {logicalName},
new String[] {"java.lang.String"});
String cursor =
(String) mbeanServerConnection.invoke(wldfDataAccessRuntime,
"openCursor", new Object[] {query},
new String[] {"java.lang.String"});
int fetchedCount = 0;
do {
Object[] rows =
(Object[]) mbeanServerConnection.invoke(wldfDataAccessRuntime,
"fetch", new Object[] {cursor},
new String[] {"java.lang.String"});
fetchedCount = rows.length;
for (int i=0; i<rows.length; i++) {
StringBuffer sb = new StringBuffer();
Object[] cols = (Object[]) rows[i];
for (int j=0; j<cols.length; j++) {
sb.append("Index " + j + "=" + cols[j].toString() + " ");
}
System.out.println("Found row = " + sb.toString());
}
} while (fetchedCount > 0);
mbeanServerConnection.invoke(wldfDataAccessRuntime,
"closeCursor", new Object[] {cursor},
new String[] {"java.lang.String"});
} catch(Throwable th) {
th.printStackTrace();
System.exit(1);
}
}
private static MBeanServerConnection lookupMBeanServerConnection ()
throws Exception {
// construct JMX service URL
JMXServiceURL serviceURL;
serviceURL = new JMXServiceURL("iiop", "localhost", 7001,
JNDI + "weblogic.management.mbeanservers.runtime");
// Specify the user, password, and WebLogic provider package
Hashtable h = new Hashtable();
h.put(Context.SECURITY_PRINCIPAL,"weblogic");
h.put(Context.SECURITY_CREDENTIALS,"weblogic");
h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES,
"weblogic.management.remote");
// Get jmx connector
JMXConnector connector = JMXConnectorFactory.connect(serviceURL,h);
// return MBean server connection class
return connector.getMBeanServerConnection();
} // End - lookupMBeanServerConnection
}