In my latest article here at VB-2-The-Max ("COM+ Centric Assert") I promised to deliver a three-part article about tracing. Here I am. Santa Claus is fulfilling your wish list for goodies, I take care of the programming stuff<g>.
In this first part I will start with a general discussion about tracing and then discuss how trace calls can be sent from your stored procedures in SQL Server. On the way I will also briefly discuss a client tool for viewing the trace messages. In part two I will focus on tracing the execution of configured COM+ components and in the third part I will discuss tracing in ASP and talk a little more about the client tool.
Before I discuss tracing in the context of stored procedures, let’s start by giving an overview of the complete article.
PURPOSE OF THIS ARTICLE
Some of you are probably thinking that you don’t need to see another solution for tracing today, especially not since the .NET Framework has a nice one built in. On the other hand, I guess that most of you will delay using, VB.NET, for example, in production until next autumn at least, and perhaps you have applications that need to be built (and debugged) today?
If you use something like the trace solution that I will discuss in those three parts, it will be easy to port to the .NET solution since it’s highly centralized. (I bet you will have a much harder time with porting a lot of other stuff!) As always I find centralization and generalization of code important to get a solution that is manageable.
I will give you a concrete proposal in this article that you can use as is, to get inspiration from for building a better one or to extend to better fit your needs. My main purpose isn’t to give you a quickly hacked tracing solution. My main purpose is rather to stress the concept of tracing and get you to start using tracing in any way you find appropriate.
In the software engineering field there is a lot of discussion about "abilities" such as scalability, maintainability, portability, testability and even performability. I asked a friend who is a researcher in software architectures if they were talking about "debuggability" too, but he had never heard of it. He immediately understood what I meant, but perhaps I invented that word. I’m so proud<g>.
What I mean by debuggability is preparing your application for easy and efficient debugging when it is needed. There are several things you should do, but the single most important technique in my opinion is to add tracing support so that your application can tell you what is going on.
Perhaps you recognize the situation when your customer is calling you and he says he has a problem with the application you have built. Since it seems to be a strange problem, the only answer you can give him is that you will have to add tracing to the application and send him a new version in a couple of days. You (and your customer) are in a much nicer situation if you could just tell him to "do that" to turn trace calls on, run the scenario and send you the trace log. You haven’t solved the problem yet, but you made a very quick start!
The interactive debuggers that we are now accustomed to should of course be used as much as possible, but they have shortcomings that tracing can help to solve. Examples include easier debugging of multi-user scenarios and debugging on-line without interfering (too much) with the system. With a tracing tool you will also get a better overview when you start debugging than with a debugger, where you’re in detail mode directly.
VB’s debugger works best for debugging the application in the IDE and not the executable. If you like to debug the executable, Visual Studio’s debugger is a better choice, but even that one prefers to have an executable that isn’t optimized, for example. One way of comparing debuggers with tracing is that debuggers are better early in the project’s life cycle and tracing tools are better late. Another reason for this is that it’s quite common that the customer doesn’t allow you to install Visual Studio on any of his production servers.
You will also get primitive profiling capabilities for free when you use a tracing tool. That way you can see where most of the time is spent in your code and where you should spend your optimization resources. No, a simple trace tool does not make it possible to skip a real profiling tool, for example, for checking the code coverage of your testing, but I use it quite often for quickly finding bottlenecks.
Another use for your trace logs will be to use them for review. I really like the idea of design and code review, and reading trace logs are sort of taking it to the next level. Once when I gave my course "COM+ Component Services and VB", one of the attendees had an idea when I talked about tracing. He said that it would be quite simple to use the trace log to automatically check if the documentation he had created as activity diagrams in Rational Rose was correct. That would be one way of getting better documentation and documentation that has evolved with the system.
I’ve decided to categorize my trace messages the following way:
"Assert" should be used in your assert-sub (as I discussed in "COM+ Centric Assert") for sending signals about broken assertions as trace-calls. "Begin" and "End" should be used when a procedure is entered and exited.
"Error" should be used in your general sub where you raise errors. You shouldn’t skip ordinary logging of errors to the event log, a database or something like that just because you send trace-calls. Think about trace calls as something that might be activated and that somebody might be listening to. Error logging should always be active so that information can be used afterwards even if no one was actively listening at the moment when the problem occurred.
Finally "Msg" should be used at specific places in the code where you like to take a look at certain variable values or say that a certain section in code was entered.
WISH LIST AND DESIGN GOALS OF MY TRACE SOLUTION
Something like a year ago I decided on the following requirements and design goals for my tracing solution:
- Collect information from ASP, COM+ components and stored procedures in SQL Server
I’d like to have the possibility to view the calls from my ASP page, some subs/functions in an ASP include layer, then through all the layers in COM+ and finally to the stored procedures in SQL Server. That way I will get a good understanding of what is going on, no matter which server process the problem lies in.
- Make it possible to view information from several servers as one single trace log
What I said in the previous bullet should be true even if the processes are spread over several physical machines.
- Activation/deactivation online
It’s preferable that you can have a single version of the executable so that you don’t have to swap a DLL, for example, before you can start tracing. When you decide that you need to start to trace something, you should be up and running in a minute.
- Small overhead, especially important when not activated
The overhead should be small when the tracing support isn’t activated but is only there waiting to be activated. It should be possible to easily strip out the tracing support when the system has been running smoothly for a while. The trace calls shouldn’t be deleted from the source file, but excluded only from the executable.
It’s very important to make your debug tools interfere as little as possible. That goes for your assertions and your trace calls as well. If you get side effects from those, then they will create problems of their own or they may hide problems that appear when the debuggability tools are taken away (for example with conditional compilation).
- Filtering possibilities
You will very quickly collect a lot of tracing information so it’s necessary to have the possibility to filter the trace information. This applies both before the trace calls are sent and in the client tool, where the trace calls should be shown.
- Easy to use for developers
It should be easy to activate/deactivate tracing, but also easy to do the trace calls in your code.
- Carry a lot of information with each trace call
It’s also important to send specific data to get consistent trace information when it’s time to analyze the data. The name of the procedures, process ID, thread ID, hostname and so on should always be added. The same goes for more COM+ centric stuff such as IsInTransaction and IsSecurityEnabled.
I created the first version of my tracing tool a year ago so I guess it was quite OK directly, regarding my needs. OK, I confess that I have made some small changes to the stored procedure version recently and I will make some small changes to the COM+ solution and the client tool too, before I write parts two and three of the article.