Yet another debugging technique

R

Roedy Green

If you look at my website, mindprod.com, you will see that a large
part of it is generated by various computer programs.

If I run the output through HTMLValidator, or eyeball it, or view it
in a browser, it is generally pretty easy to find errors. The hard
part is figuring out where that error was generated in the
corresponding code.

I had an idea years ago for a tool to solve that problem, but no one
was interested. It worked like this:

In debug mode there is a hook in the text-output functions to,
whenever you write a line, makes a log entry including the offset in
the file and where in the program it called the io that wrote it.
The log entry would be in compact binary (something like serialized
ObjectStream), but in essence it would look something like this:
at com.mindprod.prices.Prices.emitDetailsAndManual line:1059

The output is perfectly normal and you can do anything you would
normally do with it. However, there a magic viewer for the file.
When you right click on any character, it will tell you the program
and line number that wrote it. It looks the filename and offset up in
the log file, which is massaged to make finding fast.

I needed such a tool tonight, but I had too many things on my plate
and did not have time. Further I did not know how to insert the hook
without changing the names of the io methods.

So I cooked up something a little more primitive.


/**
* tell you where in the code you are, class/method/line
*
* @param depth Set to 1 if you call youAreHere directly.
* Set to 2 if you call it indirectly via a piece of
code that
* does something with the String it generates, and
you
* really want the location of its caller.
*/
public static String youAreHere( int depth )
{
final Throwable t = new Throwable();
final StackTraceElement[] es = t.getStackTrace();
final StackTraceElement e = es[ depth ];
return "at "
+ e.getClassName()
+ "."
+ e.getMethodName()
+ " line:"
+ e.getLineNumber();
}

I then peppered my code with calls to this method. I inserted the
String it gives back into the output stream inline, as an HTML
comment.

<!-- at com.mindprod.prices.Prices.emitDetailsAndManual line:1059 -->

By turning a debug switch on and off I could control
whether these comments were inserted.

There is a problem. You can't just insert <!-- ... --> ANYWHERE in
HTML. So I had to manually back off and suppress the insertion in
spots where the comment could confuse an HTML parser, e.g. inside
comments or inside macros which are officially comments. If I had a
tool such as above, that would not be a problem. The generated stream
would be intact no matter where I made my log entries.
 
S

Silvio

If you look at my website, mindprod.com, you will see that a large
part of it is generated by various computer programs.

If I run the output through HTMLValidator, or eyeball it, or view it
in a browser, it is generally pretty easy to find errors. The hard
part is figuring out where that error was generated in the
corresponding code.

I had an idea years ago for a tool to solve that problem, but no one
was interested. It worked like this:

In debug mode there is a hook in the text-output functions to,
whenever you write a line, makes a log entry including the offset in
the file and where in the program it called the io that wrote it.
The log entry would be in compact binary (something like serialized
ObjectStream), but in essence it would look something like this:
at com.mindprod.prices.Prices.emitDetailsAndManual line:1059

The output is perfectly normal and you can do anything you would
normally do with it. However, there a magic viewer for the file.
When you right click on any character, it will tell you the program
and line number that wrote it. It looks the filename and offset up in
the log file, which is massaged to make finding fast.

I needed such a tool tonight, but I had too many things on my plate
and did not have time. Further I did not know how to insert the hook
without changing the names of the io methods.

So I cooked up something a little more primitive.


/**
* tell you where in the code you are, class/method/line
*
* @param depth Set to 1 if you call youAreHere directly.
* Set to 2 if you call it indirectly via a piece of
code that
* does something with the String it generates, and
you
* really want the location of its caller.
*/
public static String youAreHere( int depth )
{
final Throwable t = new Throwable();
final StackTraceElement[] es = t.getStackTrace();
final StackTraceElement e = es[ depth ];
return "at "
+ e.getClassName()
+ "."
+ e.getMethodName()
+ " line:"
+ e.getLineNumber();
}

I then peppered my code with calls to this method. I inserted the
String it gives back into the output stream inline, as an HTML
comment.

<!-- at com.mindprod.prices.Prices.emitDetailsAndManual line:1059 -->

By turning a debug switch on and off I could control
whether these comments were inserted.

There is a problem. You can't just insert <!-- ... --> ANYWHERE in
HTML. So I had to manually back off and suppress the insertion in
spots where the comment could confuse an HTML parser, e.g. inside
comments or inside macros which are officially comments. If I had a
tool such as above, that would not be a problem. The generated stream
would be intact no matter where I made my log entries.


Unless you would have some really crappy code most IO calls in an HTML
generating application would be inside a very small general purpose
utility class. You would need an entire stack trace at every output
position to be able to actually pinpoint a bug.
And even then it would only work for simple cases where output would not
be determined mostly by complex state handled by more or less generic code.
 
R

Roedy Green

Unless you would have some really crappy code most IO calls in an HTML
generating application would be inside a very small general purpose
utility class. You would need an entire stack trace at every output
position to be able to actually pinpoint a bug.

I think, in practice, the depth of the stack you want too sample is
constant. Perhaps if it is variable, the code would have to set it
dynamically, yuch! Perhaps the snapshot taker could be given a list
of methods NOT of interest. When it hits one, it snapshots one deeper
in the stack.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top