Mining WebLogic Diagnostic Data with XSLT
Pages: 1, 2, 3

Add a system diagnostic module to your domains

The instrumentation specified in an application's weblogic-diagnostics.xml file will not be applied unless there is a system diagnostic module with instrumentation enabled, and the system diagnostic module is targeted to the WebLogic Server instance. This is a feature; it allows you to enable or disable the instrumentation without having to alter your application, and it also allows instrumentation to be enabled on a server-by-server basis.

If you change the targeting of the system diagnostic module, or change whether instrumentation is enabled, you must fully redeploy your application for the change to take effect. Only a full redeployment will perform the AOP weaving process and change the instrumentation. Stopping and starting the application through the WebLogic console is not sufficient. Instead, do one of the following:

  • Use the WLST redeploy() command.
  • Untarget the application, apply the change, and then retarget the application.
  • Restart your servers.

Whenever you change weblogic-diagnostics.xml, you must also do a full redeployment.

You can create a system diagnostic module using the WebLogic console. This results in a file in the config/diagnostics directory of your domain which you can compare with the following example:

<?xml version='1.0' encoding='UTF-8'?>
<wldf-resource xmlns="http://www.bea.com/ns/weblogic/90/diagnostics"
 xmlns:sec="http://www.bea.com/ns/weblogic/90/security"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:wls="http://www.bea.com/ns/weblogic/90/security/wls"
 xsi:schemaLocation="http://www.bea.com/ns/weblogic/90/diagnostics http://www.bea.com/ns/weblogic/920/diagnostics.xsd">
  <name>MySystemDiagnosticModule</name>
  <instrumentation>
    <enabled>true</enabled>
  </instrumentation>
  <harvester>
    <enabled>true</enabled>
    <sample-period>10000</sample-period>
    <harvested-type>
      <name>weblogic.management.runtime.WorkManagerRuntimeMBean</name>
      <harvested-attribute>CompletedRequests</harvested-attribute>
      <harvested-attribute>PendingRequests</harvested-attribute>
      <harvested-attribute>StuckThreadCount</harvested-attribute>
      <harvested-instance>com.bea:ApplicationRuntime=WLDF,Name=default,ServerRuntime=AdminServer,Type=WorkManagerRuntime</harvested-instance>
    </harvested-type>
    <harvested-type>
      <name>weblogic.management.runtime.JTAStatisticsRuntimeMBean</name>
      <harvested-attribute>TransactionCommittedTotalCount</harvested-attribute>
      <harvested-attribute>TransactionRolledBackTotalCount</harvested-attribute>
      <harvested-instance>com.bea:Name=JTARuntime,ServerRuntime=AdminServer,Type=JTARuntime</harvested-instance>
    </harvested-type>
  </harvester>
  <watch-notification></watch-notification>
</wldf-resource>

As well as enabling instrumentation, I've specified that various MBean attributes should be harvested. We'll play around with some of this harvested data later.

The Diagnostic Context

An interesting feature of WLDF not commonly found in other tools is its ability to create and propagate a diagnostic context. This diagnostic context uniquely identifies a particular request, and flows across synchronous calls to other WebLogic Server instances. The diagnostic context includes a unique ID (for example, 583c10bfdbd326ba:-43487c71:112bda0af31:-7ff4-00000000000001b7). You can use this ID to trace event flows across servers.

Related to the diagnostic context is the notion of requesting dyeing. A DyeInjectionMonitor can be used to filter the events that are recorded based on various request characteristics (user identity, protocol type, IP address, and so on). This is a powerful way of focusing what you record, but I won't be using this feature in the course of this article. For more information, please refer to the WebLogic documentation.

The diagnostic context adds a very small processing overhead: essentially, it's the cost of generating the unique ID, and passing it around with every request. I consider the overhead to be negligible. However, since the WLDF works on the principle of "Only pay for what you use," the diagnostic context is generated only if any of the following is true:

  • A DyeInjectionMonitor is enabled.
  • Instrumentation is enabled.
  • The diagnostic context is specifically enabled for the server through the Diagnostics / Context page of the console.

The behavior of diagnostic context generation was rationalized to follow these rules in WebLogic Server 9.2. If you are using WebLogic Server 9.0 or 9.1, you might find you have to enable the diagnostic context through the console, and that doing this overrides any inbound context, so be careful to make this change only on the servers that receive initial requests.

Use WLST to extract data from the diagnostic archive

WebLogic stores diagnostics in a diagnostic archive local to each server.

Step 2 - export data
Figure 3. WLST is used to export data from the diagnostic archive.

The diagnostic archive contains event and harvested metric data in a binary format. As shown in Figure 3, the data can be exported to an XML format using the WebLogic Scripting Tool (WLST), using either the exportDiagnosticData or exportDiagnosticDataFromServer commands. For example:

exportDiagnosticData(storeDir="/work/domain/servers/server1/data/store/diagnostics",
  logicalName="EventsDataArchive", exportFileName="server1-events.xml")

I'll be using two types of data, event data ( logicalName="EventsDataArchive") and harvested metric data ( logicalName="HarvestedDataArchive"). Both exportDiagnosticData and exportDiagnosticDataFromServer have options that allow you to filter data, by time or through a full WLDF query. You should use these filter options to limit the size of the exported XML files. This is particularly important as the Java XSLT implementation that we will use does not scale well with large input files. Here's an example of filtering by a particular diagnostic context ID:

exportDiagnosticData(storeDir="/work/domain/servers/server1/data/store/diagnostics",
  logicalName="EventsDataArchive", exportFileName="events.xml",
  query="CONTEXTID='583c10bfdbd326ba:58f87d21:1126b53f6ec:-7ff3-0000000000000c2a'")

Beware when trying to use exportDiagnosticData multiple times from the same WLST process to access archive files from different servers. There's a minor problem with this command; the second and subsequent times it is used, it will continue to refer to the original archive file that was opened. Work around this problem by using a separate WLST process to access each archive.

If you look at the exported XML data, you'll see the XML conforms to an abstract schema that models a set of DataRecords consisting of ColumnData values for various columns. The XML file starts with a DataInfo element that contains the names of the columns and their Java types. These columns are slightly different for the event and harvested data files in which we are interested.

How to Run an XSLT Stylesheet

So now we have some XML. Before we get to our first XSLT stylesheet, here's a useful Jython script you can use to process an XML document with a stylesheet:

import sys

from java.io import FileReader, PrintWriter
from java.lang import System
from javax.xml.transform import TransformerFactory, Transformer
from javax.xml.transform.stream import StreamSource, StreamResult

def transform(source, stylesheet, result, parameters):
    transformer = TransformerFactory.newInstance().newTransformer(stylesheet)

    for (p, v) in parameters: transformer.setParameter(p, v)

    transformer.transform(source, result)

if __name__ == '__main__':
    args = sys.argv[1:]
    parameters = []
    
    while args and args[0].startswith('-'):
        try:
            i = args[0].index('=')
        except ValueError:
            parameters.append((args[0], ""))
        else:
            parameters.append((args[0][1:i], args[0][i+1:]))

        args = args[1:]
    
    if len(args) == 1:   source = StreamSource(System.in)
    elif len(args) == 2: source = StreamSource(FileReader(args[1]))
    else: raise "Usage: <jython|wlst> process.py -<parameter>=<value> <stylesheetfile> [inputfile]"

    stylesheet = StreamSource(FileReader(args[0]))
    result = StreamResult(PrintWriter(System.out))

    transform(source, stylesheet, result, parameters)

    stylesheet.reader.close()
    source.reader and source.reader.close()
    result.writer.close()

You can call this directly from Jython, but as WLST comes with WebLogic Server 9, I'll show you an example of using WLST to start this script. First, set your environment (for example, source setDomainEnv.sh). Then run process.py with:

java weblogic.WLST process.py stylesheet.xsl input.xml > output.xml

The output will go to stdout, so we use shell redirection to send it to output.xml. Alternatively, you might use the shell pipe operator to chain multiple process.py processes together. If you have Jython installed, you'll get a faster start-up time by using jython in place of java weblogic.WLST.

Some of our stylesheets take parameters that control their behavior. process.py lets you specify stylesheet parameters as follows:

java weblogic.WLST process.py -myparameter=value stylesheet.xsl input.xml > output.xml

If you are using a Microsoft Windows shell, you'll need to quote the parameters, for example, "-myparameter=value".

Pages: 1, 2, 3

Next Page ยป