So far, we kept adding more detailed information in the main report produced by our analyzer. Such detailed reports are useful to allow an expert in some problem area to read through and manually diagnose various problems that are present in the system from which the dump is now being analyzed. But it would be nice, when possible, if the analyzer could automatically diagnose some problems and generate a short statement of the problem that was found, that even someone who is not at all an expert can readily see and understand. This is the purpose of the facility to emit
observations from analyzers. An
observation is a short statement of a problem or potential problem that has been automatically detected by the analyzer, and brought to the attention of the end-user.
For this example, we will assume that a good indication of a potential problem would be if the total number of threads currently allocated across all the pools, more than 80% of the total maximum number of threads allowed if all the pools were completely used; this suggests that the WebSphere Application Server process is using almost all its allowed resources and is close to being overloaded. Note that this might actually not be a very good indicator of a potential problems in the real world... but it's simple and this will do to illustrate the principle in this small example.
We implement this by adding the following code near the end of our
produceReport(), after the point where we have finished computing the values of the
numberOfAllocatedThreads and
numberOfPossibleThreads state variables that we added in the earlier topic on
Extracting Values from Data Structures:
/*
* A threshold to warn of possible thread overload (% of allocated vs. possible threads)
* (not necessarily appropriate for actual problem detection; just to show the principle of such observations)
*/
final int THREAD_OVERLOAD_THRESHOLD = 80;if (numberOfAllocatedThreads > ((THREAD_OVERLOAD_THRESHOLD / 100.0f) * numberOfPossibleThreads)) {
logMessage(IMessageLogger.LEVEL_DBDA_OBSERVATION_LOW,
"(minor observation) This process is currently using more than {0}% of all possible threads ({1}/{2})",
new Object[] { new Integer(THREAD_OVERLOAD_THRESHOLD),
new Integer(numberOfAllocatedThreads),
new Integer(numberOfPossibleThreads) },
out);
}
The output form this, shown at the very beginning of the output from the entire run of the Dump Analyzer tool, well before the main report output from our analyzer, might look something like this:
DumpAnalyzer V:1.2.0.20080114185939 starting analysis of server1.dmp.zip===========================================================================
- Observations
===========================================================================(minor observation) This process is currently using more than 80% of all possible threads (380/433)
===========================================================================
2. Analysis results
===========================================================================...
The "
Observations" section at the start of the output contains a list of all the
observations that have been emitted by all the analyzers that have executed during this run of the Dump Analyzer tool.
In addition, each
observation is also shown in line within the body of the report of the analyzer that emitted in, so that it can be seen in the context of other information from that report:
...Current number of pool threads: 380
Maximum possible number of pool threads: 433
---- > OBSERVATION: (minor observation) This process is currently using more than 80% of all possible threads (380/433)...
Note that an
observation does not necessarily reflect the certainty of a problem: we may use
observations to report significant facts that have some degree of likelihood of being associated with a problem, but without a certainty. The key, though, is that the observations should be few enough, and pertinent enough, that a non-expert user should be able to browse them quickly and get a good insight in potential problems, without having to read through and understand the entire report. The typical example of an
observation, which in this case is a sure indication of a problem, is "deadlock detected".
The code to emit this
observation is simple: we simply perform whatever computation is necessary in the body of the analyzer to determine if the
observation is warranted and, if so, we call the
logMessage() method to emit the
observation.
This method is inherited from the
WASAnalyzerBase class from our analyzer (actually from a deeper common base class that
WASAnalyzerBase itself is based on). It takes as parameters:
- a severity (high/medium/low) that is used, by convention, to reflect the likelihood that this observation is an indication of a real problem, vs. simply a suspicious fact that may or may not turn out to be a real problem
- a message and a variable set of parameters for this message, to be formatted according to the syntax from the standard java.text.MessageFormat class
- an optional reference to a report object. If this reference is not null, the observation is inserted in that report and included in the summary of all observations at the head of the Dump Analyzer tool output. If the report reference is null, then the observation is shown only in the summary of all observations at the head of the Dump Analyzer tool output, but not inside any report.
You may have noticed that the definition and the behavior of the
logMessage() method used here, is in many ways similar to the
logExceptionMessage() method that we used in the section
Extracting Values from Data Structures to report an exception that occurred while extracting some information from a data structure. This is no accident. In general, any message being emitted by an analyzer (
observation, errors, other informational messages) can be emitted by a call to the
logMessage() method with an appropriate severity level as argument; we simply use several pre-defined severity levels to correspond to
observations. All these pre-defined severity levels are explained in detail in the API documentation for the
IMessageLogger interface.
logExceptionMessage() is simply a short-cut that can be used to pre-format and filter some of the parameters before a call to
logMessage(), to be used specifically when we want to report an error that occurred during analysis, and for which we have a particular exception object in hand.
Note that in the terminology of the Dump Analyzer framework:
- An observation corresponds to some problem or potential problem that has been detected in the system from which we are currently analyzing a dump. It is a desired output from the Dump Analyzer tool and its analyzers, expected even if the tool and the analyzers are absolutely perfect and bug-free.
- An error corresponds to a problem that occurred during the analysis itself, due to a corruption in the dump file, or a defect in the Dump Analyzer tool or one analyzer, or some other difficulty that prevents a perfect analysis. It is an undesirable (but not always avoidable) output from the Dump Analyzer tool and its analyzers.
Invoking DTFJ Functions