# Exercise 1.4: Creating more advanced probes

Before you begin, you must complete Exercise 1.3: Deploying your probe.

Probekit can be used to solve many real-world debugging and runtime-analysis problems. You've now learned the basics of writing and deploying probes, so this and the following lesson will not walk you through the activities, but instead provide suggestions for probes that you might write to investigate your own application.

### Investigating an exception

Assume that some method in a servlet occasionally throws an exception. The log message that comes out is not very helpful; it doesn't clearly indicate what the problem is. To get more information, you can write a probe that executes whenever the method throws an exception, and the Java code in the probe's fragment can log the exception message and also the arguments to the method. This will help you see why the exception is being thrown.

When you write and deploy this probe, note the following points:

- Write an ExceptionExit fragment using the exceptionObject and args data items:

      System.out.println("[Exception probe triggered!]");
      for (int i = 0; i < args.length; i++) {
      	System.out.println("Argument " + i + "=" + args[i]);
      }

- When you set filters to target the probe, include the class and method you want to investigate; exclude all others.

### Investigating a method's erratic performance

Here is a fairly intricate probe example. Let's say there is a method in your program that usually executes quickly but occasionally takes a long time (longer than 100ms, for example).

You can write a probe that takes note of the entry and exit times whenever the method executes. When the execution time is short, the probe does nothing. When the execution time is long, the probe reports the arguments to the method and other important information about program state at the time. This allows you to determine the circumstances that lead to the longer execution times.

When you write the probe, note the following points:

- Include a "fragment at class scope":

  You can use the "fragment at class scope" feature of Probekit to write a Java code fragment that will be compiled into the generated class outside of any method. In this case the fragment is used to define a static field called `entryTime` that will be used by both the entry and exit fragments.

  To add this element to a probe, click the `Probe` element in the Probekit editor; the editor displays a field for you to enter the Java code for the fragment at class scope:

      static long entryTime;
      static final long thresholdDuration = 100;

- Include an "entry" fragment:

      entryTime = System.currentTimeMillis();

- Include an "exit" fragment using the className, methodName, and thisObject data items:

      long now = System.currentTimeMillis();
      if ((now - entryTime) > thresholdDuration) {
      	System.out.println(
      		"[Spent a long time in " +
      		className + "." + methodName +
      		": this=" + thisObject + "]");
      }

- When you set filters to target the probe, include the class and method you are investigating; and exclude all others.

At method entry, this probe records the current time. At method exit, the probe compares the current time and the recorded entry time, and if more than a certain amount of time has elapsed (the amount you specified in "thresholdDuration"), it prints a report using System.out.

### Investigating erratic performance in a recursive or multi-threaded method

The probe that we just discussed doesn't work for methods that are recursive (directly or indirectly), and it doesn't work for methods that might be running in multiple threads at the same time. To solve the recursive problem, you could record the entry times on a Stack; to solve the multi-threaded problem, you could store the stack in a ThreadLocal variable.

Here is what you need to create a recursion-safe, thread-safe version of the probe:

- Fragment at class scope:

      static ThreadLocal tl = new ThreadLocal() {
         public Object initialValue() {
            return new Stack();
         }
       };
       static long thresholdDuration = 100;	// Report if time is over 100ms

- Entry fragment:

      long now = System.currentTimeMillis();
      Stack stk = (Stack)tl.get();
      stk.push(new Long(now));

- Exit fragment (uses the same data items as the simple form):

      long now = System.currentTimeMillis();
      Stack stk = (Stack)tl.get();
      long entryTime = ((Long)stk.pop()).longValue();
      if (now - entryTime > thresholdDuration) {
         System.out.println(
            "[Spent a long time in " +
            cName + "." + mName +
            ": this=" + thisObj + "]");
       }

Continue the tutorial with Exercise 1.5: Using a runtime library for more complex probe logic.

Terms of use | Feedback
(C) Copyright IBM Corporation 2000, 2005. All Rights Reserved.