IntelliTrace – What we collect
When introducing a new feature like IntelliTrace you’re bound to get a lot of incorrect information floating around about exactly what the feature is and how it works. In particular with IntelliTrace I see lots of confusion about exactly what data is collected by IntelliTrace while running. While I’ve mentioned what data IntelliTrace collects on and off in various blog posts I figured that it might be smart to get all the info codified into one blog post.
What IntelliTrace doesn’t collect
When customers first hear about IntelliTrace what is usually conjured to mind is the ability to step backward though their code, checking to see what happened previously with all the full features and information of normal live debugging. It would be wonderful if we could fully deliver on that vision with IntelliTrace but the restrictions of both keeping program execution time overhead and log file size down while still providing useful information prevent that. If your vision of IntelliTrace was collecting the whole world of data and being able to step back though it then the section below might be a bit of a disappointment. But we feel that the choices made really have given the best balance between speed and size of use and collection of valuable data for just about all users.
What IntelliTrace does collect
So now that we’ve set the expectation that IntelliTrace is not going to be collecting all the data that you have access to in the live debugger then what exactly is it collecting? Well the answer to that depends on if we are collecting data at an IntelliTrace event, at a debug stopping event or if we are collecting data at a method entry or exit in calls mode. While the details of what was collected are different in each case we do collect some data in common regardless of the mode. In particular we always collect system information when first starting collection, module load and unload and thread starting and ending events. With the module and the thread events we are able to keep the modules and threads debugger windows correctly updated when you are moving back into your program’s execution.
Another place that we always collect data at regardless of what mode we are running in is at debugger stopping points such as break points. At these point we will collect all basic data types (and all basic data types one level off of objects) that are examined or evaluated in the debugger. This is very handy when you examine a value, take a step forward and see that the value is changed but didn’t make a note of the previous value. Since you examined it (causing IntelliTrace to collect the data on that stopping point) just take a step back in time to see the variable at its previous value. In the example below I’ve taken a few steps forward in the debugger, notice the step events in the flat list on the right, then I’ve jumped back in time to one of the previous debugger steps. In the locals window you can see the variables that were collected at that point. Those will also show up correctly when hovering over those items for datatips or pinnable datatips.
Data Collection at IntelliTrace events
When you hit an IntelliTrace event during your program’s execution you will collect data that has been specifically configured to be captured there. Inside the collectionplan.xml file IntelliTrace events can specify either the collection of basic local variables via DataQuery elements or provide classes that inherit IProgrammableDataQuery to perform more complex data retrieval. The upshot of this is that at IntelliTrace events we only collect a small amount of data that is custom tuned to be relevant to the specific event being examined. If you move back in time to an IntelliTrace event you will most likely just see the [IntelliTrace data has not been collected] message when mousing over any local variables.
This highly guided data collection is intended to keep the overhead when running in just events mode as low as possible. By default IntelliTrace is always running in this mode for managed application so even minor degradations in performance can have a really big effect. It’s important to know that while unsupported officially you can create your own custom IntelliTrace events for richer debugging on your own applications. And for these events you can use the same DataQuery / IProgrammableDataQuery system to collect just the data known to be most important to you at all these points.
Below I’ve shown an example of IntelliTrace being set back to an event in which an Environment Variable was accessed. In this case the event has been configured to collect data on the name of the variable being access which appears both in the event and in the event item in the autos window.
Data Collection in calls mode
When you have a little performance overhead to spare and want to collect much deeper IntelliTrace data you can jump into the options pages and turn on calls mode. In this mode in addition to data collection at IntelliTrace events data is also collected at function entry and exit points. At function entry points we will collect all basic types and basic types one level off of objects for all the parameters that are passed into the function. Also we’ll apply the same principle for the return values of the function. By capturing parameters and return values you can often treat the actual function as a black box and at the lowest cost in terms of collection you can tell what function is spitting out bad data that’s leading to a crash or other error.
Pictured below is IntelliTrace stopped and moved back from a breakpoint to a function enter point. In the autos window you can see that all the primitive data type off of the GizmoManager object that was passed in as a parameter have been collected and are available to view.
Comments
- Anonymous
March 19, 2010
Hi Ian, First off, I think IntelliTrace is a great first step. What I'd really like to see is what you described in the first paragraph of this article. Full-fidelity historical debugging. Please let me decide how much of a performance hit I am willing to take in the name of debugging. When I have an issue I need ALL of the information available. Let me turn on/off local variables, etc. Let me decide how big an iTrace file is too big. if you are concerned about folks using it without full understanding, make it harder to find and put a nice warning on it. Give me the information that I need to make an informed decision, but leave the decision up to me. Thanks,
- Steve
Anonymous
March 19, 2010
Steve, The issue more is that a solution like IntelliTrace is just really different at a structural level then a solution that would provide full fidelity debugging. It's not just desiring that customers have full understanding but just plain old limitations with the current way that we log data. There is no real way to turn the dial to eleven that we have hidden that we just don't want customers to use, it just doesn't exist. To get that you need something more like instruction level tracing and replay, I think something like Valgrind uses a solution of that type. And that's really an entirely different technology type that IntelliTrace is with a whole different set of advantages and disadvantages. I'm glad that you think that IntelliTrace is a good first step though. I've found via my own dogfooding usage that on top of the default coverage the ability to roll custom events can get you a pretty solid recording of a debug session with a really reasonable overhead. ~IanAnonymous
March 21, 2010
The comment has been removedAnonymous
March 24, 2010
The comment has been removedAnonymous
April 14, 2010
The comment has been removedAnonymous
May 09, 2010
Hi Ian, Thanks for your answer, and cheers on the 'Pinnable Data-tips' blog post - a interesting and thoughtful read, like always. I have another question regarding what the Intellitrace debugger collects - does it collect (or can I somehow force it to collect) object IDs? IE, if I'm looking at the parameter of a method at a certain point in time, and then jump to a different point in time, can I check whether i'm looking at the same instance? Can I make a retrospective Object ID?Anonymous
May 12, 2010
OmerRaviv, I actually wasn't sure about the Managed ID so I just went and checked. Sadly it looks like these don't show up in historical mode so we're not collecting them. Since they are not "variables" I also thinking that there is no way to add them via PDQs or DataQueries. I can see the utility in this suggestion though, so I'll see if I can get it logged on this side. ~Ian