Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
Ben Nadel at cf.Objective() 2014 (Bloomington, MN) with: Jeff McDowell and Joel Hill and Jonathan Rowny and Shawn Grigson and Jonathan Dowdle and Matt Vickers and Christian Ready and Asher Snyder and Clark Valberg and Oscar Arevalo and David Bainbridge and Josh Siok
Ben Nadel at cf.Objective() 2014 (Bloomington, MN) with: Jeff McDowell@jeff_s_mcdowell ) , Joel Hill@Jiggidyuo ) , Jonathan Rowny@jrowny ) , Shawn Grigson@shawngrig ) , Jonathan Dowdle@jdowdle ) , Matt Vickers@envex ) , Christian Ready@christianready ) , Asher Snyder@ashyboy ) , Clark Valberg@clarkvalberg ) , Oscar Arevalo@oarevalo ) , David Bainbridge ( @redwhitepine ) , and Josh Siok@siok )

Finding Template Execution Stack in ColdFusion

By Ben Nadel on
Tags: ColdFusion

There have been times when I wanted to get a list of all the ColdFusion templates that were executed during a single page call. I wanted to get a list similar to that of the debugging information that shows at the bottom of the page when debugging output is turned on. To figure it out, I looked at the template that handles the current debugging. When you look in the file, getting this information is actually really simple. To get a stack trace, you just have to create a ColdFusion service factory and ask for the debugging service:

  • <!--- Create ColdFusion service factory instance. --->
  • <cfset objFactory = CreateObject(
  • "java",
  • "coldfusion.server.ServiceFactory"
  • ) />
  •  
  • <!--- Get the debugging service from the service factory. --->
  • <cfset objDebugging = objFactory.GetDebuggingService() />
  •  
  • <!---
  • Get the events table. This includes all events
  • that have taken place, not just template executions.
  • This is returned as a query.
  • --->
  • <cfset qEvents = objDebugging.GetDebugger().GetData() />
  •  
  • <!---
  • Now that we have all the events in query format, do a
  • query of queries to get only events that were template
  • executions event.
  • --->
  • <cfquery name="qTemplates" dbtype="query">
  • SELECT
  • line,
  • parent,
  • template,
  • endtime,
  • starttime
  • FROM
  • qEvents
  • WHERE
  • type = 'Template'
  • ORDER BY
  • template ASC
  • </cfquery>
  •  
  • <!--- Dump out the query of template. --->
  • <cfdump var="#qTemplates#" />

That's all there is to it. As far as I know, the ServiceFactory stuff was not documented in ColdFusion MX 6, and was considered "unsupported", but I think that in ColdFusion 7, this is a fully supported factory object and is available for programmers to leverage.

Tweet This Groovy post by @BenNadel - Finding Template Execution Stack in ColdFusion Thanks my man — you rock the party that rocks the body!


Reader Comments

Hi Ben,

Thanks for posting this -- just this morning I needed code to solve this problem (for my debugging library) and your sample works great. I've refactored it into a UDF, and made a few tweaks. Would you mind if I submitted the UDF to CFLib.org? I'll of course give you credit for the original work.

Thanks again.
Nolan

Hey Ben,

When I try implementing this I keep getting a "Value Must Be Initialized Before Use" error. I am assuming this may have to do with the fact that I do not have debug turned on inside CF Administrator. Is it possible in invoke this without turning on debug in the administrator...or is there a way to turn on debug for one page instance and not the entire server? There are times when I only want to debug for a single page that is giving me trouble but I don't want to risk showing debug details to everyone, especially in a production environment.

Any insight would be most excellent and much appreciated.

Ron

@Ron,

From what I remember, you *might* need to have debugging turned on.

You could try to throw an error and then catch it and look at the tag context... this is an "expensive" approach; but, if you're doing it for debugging, it should work.

I am doing code cleanup on a project and need to collect the templates that are unused. If we have the set of templates used then obviously the unused are just the complement of that set. I use a similar method the collect the templates(and if a cfc, the method called):
<cftry>
<cfobject action="CREATE" type="JAVA" class="coldfusion.server.ServiceFactory" name="factory">
<cfset cfdebugger = factory.getDebuggingService()>
<cfcatch type="Any"></cfcatch>
</cftry>
<cfobject action="CREATE" type="JAVA" class="java.lang.String" name="ST">
<cfset qEvents = cfdebugger.getDebugger().getData()>
<cfquery dbType="query" name="cfdebug_templates_summary" debug="false">
SELECT distinct template
FROM qEvents
WHERE type = 'Template'
</cfquery>
<cfloop query="cfdebug_templates_summary">
<cfscript>
//need a java string so we can split on a regex
temp=ST.init(template);
a=temp.split("\sfrom\s");
temp2=trim(a[arraylen(a)]);
re="\|(.*?)(\(|\])";
//now find the method called
sRet=refind(re,temp,1,true);
if(arraylen(sRet.pos)>1){
temp3=trim(mid(temp,sRet.pos[2],sRet.len[2]));
}else{
temp3="";
}
a=ST.init(temp2).split("wwwroot\\");
out=a[arraylen(a)];
if(temp3!=""){
out&=":" & temp3;
}
</cfscript>
<cflog file="templatesused" text="#out#">
</cfloop>

Any ideas on how to pull the template list if you *don't* have debugging turned on? I can't get debugging turned on but it would sure save my sanity if I could see that template stack.

@Ben

"@Ron, From what I remember, you *might* need to have debugging turned on."

I was getting the same error as Ron, on top of Enable Request Debugging Output, I had to add my IP address to the Debugging IP Addresses.

Also the Post Comment button no worky in FireFox 4.

You can also get the tag context via:

<cfset oException = createObject("java","java.lang.Exception").init() >
<cfdump var="#oException#">

Now, what I want is to get my hands on the cfquery /cfstoredproc information including the starttime/enddimt values so I can instrument our DB interactions and run some coverage analysis. This information is available in the bjDebugging.GetDebugger().GetData() object but, as has been noted, I need to have "Enable Request Debugging" turned on. I'm sure this info is maintained somewhere in the java bowels.