Monitoring in ColdFusion

Complete monitoring tools as a CFC.

The following methods are provided in the above CFC.
getSessionCount()
getApplicationSessionCount()
getJavaMemoryInfo()
getProcessorCount()
getServerName()
getCFInstanceName()
dumpToMail()
dumpToFile()
appendToFile()
getStackTrace()

Coldfusion Monitoring Tool
<!---
ColdFusion Monitoring and Stack Trace Performance tool
Copyright 2007 	Ketan Jetty.

Note: you may have to enable the coldfusion debugging in the cfadmin

1. How to use this tool
	
A.	copy and save the following as monitor.cfc in your custom tags folders.

	create a "OnRequestEnd.cfm" with following code and save it in the ROOT
	
	<cfset monitorObj = CreateObject("component","monitor")>
	<cfset monitorObj.getStackTrace(url, form, session)>
	<cfabort>

		OR

	you can use use the following lines at the end of the page

	<cfset monitorObj = CreateObject("component","monitor")>
	<cfset monitorObj.getStackTrace("arg1","arg2","arg3")>
	<cfabort>

	note: arg1, arg2, arg3 are additionla parameters that you want to appear in the stack trace

	result: zstacktrace-2007-12-31-17-27-33.htm file will be created under c:\dump\ which contains the complete stack trace

3. dumpToFile usage
	<cfset monitorObj = CreateObject("component","monitor")>
	<cfset monitorObj.dumpToFile("arg1", "arg2", "arg3", "arg4", "arg5", "[c:/zdump.htm]")>
	or
	<cfset monitorObj.dumpToFile("arg1", "arg2", "arg3", "arg4", "arg5")>
	or
	<cfset monitorObj.dumpToFile("arg1")>
	
	result: zdump-2007-12-31-17-27-33.htm file will be created under c:\dump\ which contains the objects dump info

4. dumpToMail usage
	<cfset monitorObj = CreateObject("component","monitor")>
	<cfset monitorObj.dumpToMail("arg1", "arg2", "arg3", "arg4", "arg5", "[kjetty@yahoo.com]")>
	or
	<cfset monitorObj.dumpToFile("arg1", "arg2", "arg3", "arg4", "arg5")>	// change the email in the monitor.cfc to your email id
	or
	<cfset monitorObj.dumpToFile("arg1","arg2")>						// change the email in the monitor.cfc to your email id

	result: a mail will be sent to the provided email id, containing the dump info

5. appendToFile usage
	<cfset monitorObj = CreateObject("component","monitor")>
	<cfset monitorObj.appendToFile("arg1", "arg2", "arg3", "arg4", "arg5", "[c:/zdump_myfile.htm]")>
	or
	<cfset monitorObj.dumpToFile("arg1", "arg2", "arg3", "arg4", "arg5")>
	or
	<cfset monitorObj.dumpToFile("arg1")>
	
	result: zdump_appended.htm file will be created under c:\dump\ which contains the objects dump info appended

For additional information contact Virat Ketan Jetty
kjetty@yahoo.com
--->

<cfcomponent displayname="monitor">
	<!--- Get current sessions --->
	<cffunction name="getSessionCount" access="public" returntype="numeric" output="false">
	   <cfset var oSession = createObject("java","coldfusion.runtime.SessionTracker")>
	   <cfreturn oSession.getSessionCount()>
	</cffunction>

	<!--- Get current sessions per application --->
	<cffunction name="getApplicationSessionCount" access="public" returntype="numeric" output="false">
	   <cfargument name="appName" type="string" required="true">
	   <cfscript>
	   var oSession = createObject("java","coldfusion.runtime.SessionTracker");
	   var mySessions= oSession.getSessionCollection(arguments.appName);
	   return StructCount(mySessions);
	   </cfscript>
	</cffunction>

	<!--- getJavaMemoryInfo
	Returns a struct which contains info about the memory usage of the underlying java runtime  --->
	<cffunction name="getJavaMemoryInfo" access="public" returntype="struct" output="false">
	   <cfscript>
		  var runtime = createObject("java","java.lang.Runtime").getRuntime();
		  var stMemInfo = structNew();

		  stMemInfo.freeMemory = runtime.freeMemory();
		  stMemInfo.maxMemory = runtime.maxMemory();
		  stMemInfo.totalMemory = runtime.totalMemory();
		  stMemInfo.heapMemory = runtime.totalMemory()-runtime.freeMemory();

		  return stMemInfo;
	   </cfscript>
	</cffunction>

	<!--- getProcessorCount
	Obviously enough returns the number of processors (that the java runtime can access) in the machine. --->
	<cffunction name="getProcessorCount" access="public" returntype="numeric" output="false">
	   <cfscript>
		  var runtime = createObject("java","java.lang.Runtime").getRuntime();
		  return runtime.availableProcessors();
	   </cfscript>
	</cffunction>

	<!--- getServerName
	Get the servername from the system (should work in both windows and unix platforms) but I haven't tested it recently. --->
	<cffunction name="getServerName" access="public" returntype="string" output="false">
	   <cfset var machineName = "">
	   <cfset var factory = createObject("java", "coldfusion.server.ServiceFactory")>
	   <cfif factory.runtimeservice.getServerScope().os.name CONTAINS "Windows">
		  <cfregistry action="get"
			 branch="HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\TCPIP\Parameters"
			 entry="Hostname"
			 variable="machineName"
			 type="String" />
	   <cfelse>
		  <cfexecute name="/bin/hostname" variable="machineName" timeout="5" />
	   </cfif>
	   <cfreturn LCase(trim(machineName))>
	</cffunction>

	<!--- getCFInstanceName
	Return the instance name - useful in clusters to see which instance is handling the request. --->
	<cffunction name="getCFInstanceName" access="public" returntype="string" output="false">
	   <cfscript>
	   // code to display the java instance name
	   var jrunObj = createObject("java", "jrunx.kernel.JRun");
	   return jrunObj.getServerName();
	   </cfscript>
	</cffunction>

	<!--- dumpToMail
	dumps a max of 5 objects to a mail id. --->
	<cffunction name="dumpToMail" access="public">
		<cfargument name="data1" required="no" type="any">
		<cfargument name="data2" required="no" type="any">
		<cfargument name="data3" required="no" type="any">
		<cfargument name="data4" required="no" type="any">
		<cfargument name="data5" required="no" type="any">
		<cfargument name="mailto" required="no" type="string">

		<!--- replace the email id ---->
		<cfset var emailto = "kjetty@yahoo.com">

		<cfif IsDefined("arguments.mailto") AND IsValid("email",arguments.mailto) GT 0>
			<cfset emailto = "#arguments.mailto#">
		</cfif>

		<cfsavecontent variable="dumpVar">
			<cfoutput>
			Time: #now()#<p>
			<cfif IsDefined("arguments.data1")><cfdump var="#arguments.data1#"><hr></cfif>
			<cfif IsDefined("arguments.data2")><cfdump var="#arguments.data2#"><hr></cfif>
			<cfif IsDefined("arguments.data3")><cfdump var="#arguments.data3#"><hr></cfif>
			<cfif IsDefined("arguments.data4")><cfdump var="#arguments.data4#"><hr></cfif>
			<cfif IsDefined("arguments.data5")><cfdump var="#arguments.data5#"><hr></cfif>
			</cfoutput>
		</cfsavecontent>

		<cfmail from="support@hotbanana.com" to="#emailto#" subject="dump email - #now()#" type="text/html">
			#dumpVar#
		</cfmail>
	</cffunction>

	<!--- dumpToFile
	dumps a max of 5 objects to a file. --->
	<cffunction name="dumpToFile" access="public">
		<cfargument name="data1" required="no" type="any">
		<cfargument name="data2" required="no" type="any">
		<cfargument name="data3" required="no" type="any">
		<cfargument name="data4" required="no" type="any">
		<cfargument name="data5" required="no" type="any">
		<cfargument name="pfn" required="no" type="string">

		<cfset aPFN = "c:/dump/zDump_#DateFormat(now(),'yyyy-mm-dd-')##TimeFormat(now(),'HH-mm-ss')#.htm">
		<cfif IsDefined("arguments.pfn") AND len(trim(arguments.pfn)) GT 0>
			<cfset aPFN = "#arguments.pfn#">
		</cfif>

		<cfsavecontent variable="dumpVar">
			<cfoutput>
			Time: #now()#<p>
			<cfif IsDefined("arguments.data1")><cfdump var="#arguments.data1#"><hr></cfif>
			<cfif IsDefined("arguments.data2")><cfdump var="#arguments.data2#"><hr></cfif>
			<cfif IsDefined("arguments.data3")><cfdump var="#arguments.data3#"><hr></cfif>
			<cfif IsDefined("arguments.data4")><cfdump var="#arguments.data4#"><hr></cfif>
			<cfif IsDefined("arguments.data5")><cfdump var="#arguments.data5#"><hr></cfif>
			</cfoutput>
		</cfsavecontent>
		
		<!--- force the thread to sleep for 1 sec, to avoid overwriting the dump file --->
		<cfset thread = CreateObject("java", "java.lang.Thread")>
		<cfset thread.sleep(1000)>
		
		<!--- make sure that the c:/dumps folder has been created --->
		<cfif NOT DirectoryExists("c:/dump")>
			<cfdirectory action="create" directory="c:/dump">
		</cfif>

		<cffile action="write" file="#aPFN#" output="#dumpVar#" />
	</cffunction>

	<!--- appendToFile
	appends the dumps a max of 5 objects to a file. --->
	<cffunction name="appendToFile" access="public">
		<cfargument name="data1" required="no" type="any">
		<cfargument name="data2" required="no" type="any">
		<cfargument name="data3" required="no" type="any">
		<cfargument name="data4" required="no" type="any">
		<cfargument name="data5" required="no" type="any">
		<cfargument name="pfn" required="no" type="string">

		<cfset aPFN = "c:/dump/zDump_appended.htm">
		<cfif IsDefined("arguments.pfn") AND len(trim(arguments.pfn)) GT 0>
			<cfset aPFN = "#arguments.pfn#">
		</cfif>

		<cfsavecontent variable="dumpVar">
			<cfoutput>
			Time: #now()#<p>
			<cfif IsDefined("arguments.data1")><cfdump var="#arguments.data1#"><hr></cfif>
			<cfif IsDefined("arguments.data2")><cfdump var="#arguments.data2#"><hr></cfif>
			<cfif IsDefined("arguments.data3")><cfdump var="#arguments.data3#"><hr></cfif>
			<cfif IsDefined("arguments.data4")><cfdump var="#arguments.data4#"><hr></cfif>
			<cfif IsDefined("arguments.data5")><cfdump var="#arguments.data5#"><hr></cfif>
			</cfoutput>
			<hr />
		</cfsavecontent>
		
		<!--- force the thread to sleep for 1 sec, to avoid overwriting the dump file --->
		<cfset thread = CreateObject("java", "java.lang.Thread")>
		<cfset thread.sleep(1000)>
		
		<!--- make sure that the c:/dumps folder has been created --->
		<cfif NOT DirectoryExists("c:/dump")>
			<cfdirectory action="create" directory="c:/dump">
		</cfif>

		<cffile action="append" file="#aPFN#" output="#dumpVar#" />
	</cffunction>

	<!--- getStackTrace
	gets a complete stack trace of a request and write the output to a file [c:\zstacktrace.htm]. --->
	<cffunction name="getStackTrace" access="public" returntype="void" output="true">
		<cfargument name="arg1" required="false" default="" type="any">
		<cfargument name="arg2" required="false" default="" type="any">
		<cfargument name="arg3" required="false" default="" type="any">

		<cfset var objFactory = CreateObject( "java", "coldfusion.server.ServiceFactory" ) />
		<cfset var objDebugging = objFactory.GetDebuggingService() />
		<cfset var qEvents = objDebugging.GetDebugger().GetData() />
		<cfset var retVal = "no data" />

		<cfquery name="qTemplates" dbtype="query">
			<!--- SELECT 		parent, template, body, name, line, starttime, attributes,
						(endtime - starttime) as exeTime, stacktrace as stacktracedata
			FROM		qEvents
			ORDER BY	starttime ASC, line ASC --->
			SELECT 		parent, template, body, name, line, attributes,
						starttime, endtime, stacktrace as stacktracedata
			FROM		qEvents
		</cfquery>

		<cfquery name="qDistinctTemplates" dbtype="query">
			SELECT 		DISTINCT template
			FROM		qEvents
			ORDER BY	template
		</cfquery>

		<cfsavecontent variable="retVal">
			<script language="javascript">
				function toggleStack(obj)
				{	if (obj.style.visibility  == 'hidden' && obj.style.display  == 'none') {
						obj.style.visibility  = 'visible';
						obj.style.display  = 'block';
					} else {
						obj.style.visibility  = 'hidden';
						obj.style.display  = 'none';
					}
				}
			</script>

			<table style="font-family:verdana;font-size:9px;">
			<tr>
				<td></td><td colspan="5"><cfoutput>#DateFormat(now(),"full")#    #TimeFormat(now(),"full")#</cfoutput></td>
			</tr>
			<tr bgcolor="ffccff">
				<td></td><td>parent</td><td>template</td><td>body</td><td>line</td><td>stacktrace</td>
			</tr>
			<cfset prevStartTime = 0>
			<cfset currStartTime = 0>
			<cfset totalexetime = 0>
			<cfset color1 = "ffffff">
			<cfset color2 = "ffffee">
			<cfset tempColor = color1>

			<cfoutput query="qTemplates">
				<cfset currStartTime = starttime>
				<cfset exeTime = val(endtime) - val(starttime)>
				<cfset totalexetime = totalexetime + exeTime>

				<cfif (prevStartTime NEQ 0) AND (prevStartTime NEQ currStartTime)>
					<cfif tempColor EQ color1>
						<cfset tempColor = color2>
					<cfelse>
						<cfset tempColor = color1>
					</cfif>
				</cfif>

				<tr bgcolor="#tempColor#">
					<td valign="top" bgcolor="ffccff">#qTemplates.currentrow#</td>
					<td valign="top">#parent#</td>
					<td valign="top">#Template#</td>
					<td valign="top"><font color="blue">#exeTime# ms</font>  #name#<br>#Body#<br><cfif IsArray(attributes) AND ArrayLen(attributes)><cfdump var="#attributes#"></cfif></td>
					<td valign="top">#Line#</td>
					<td valign="top" onclick="toggleStack(id#qTemplates.currentrow#)">
						<table width="90%" bgcolor="8080c0" style="font-family:verdana;font-size:9px;"><tr><td nowrap="nowrap">[+/-]</td></tr></table>
						<br>
						<div id="id#qTemplates.currentrow#" style="visibility:hidden; display:none;">
							<cfdump var="#stacktracedata#">
						</div>
					</td>
				</tr>

				<cfset prevStartTime = currStartTime>
			</cfoutput>
			<tr style="font-family:verdana;font-size:10px;">
				<td bgcolor="ffccff"></td><td bgcolor="ffccff"><b>Total Execution time: <cfoutput>#totalexetime#</cfoutput> ms</b></td><td colspan="4"> </td>
			</tr>
			</table>
			<br>
			<table style="font-family:verdana;font-size:9px;">
			<cfoutput query="qDistinctTemplates">
			<tr>
				<td>#CurrentRow#</td><td> </td><td>#template#</td>
			</tr>
			</cfoutput>
			</table>
			<hr>
			<cfdump var="#arguments#">
		</cfsavecontent>
		
		<!--- force the thread to sleep for 1 sec, to avoid overwriting the stacktrace file --->
		<cfset thread = CreateObject("java", "java.lang.Thread")>
		<cfset thread.sleep(1000)>
		
		<!--- make sure that the c:/dumps folder has been created --->
		<cfif NOT DirectoryExists("c:/dump")>
			<cfdirectory action="create" directory="c:/dump">
		</cfif>

		<cffile action="write" file="c:/dump/zstacktrace_#DateFormat(now(),'yyyy-mm-dd-')##TimeFormat(now(),'HH-mm-ss')#.htm" output="#retVal#" />
	</cffunction>
</cfcomponent>



Ginger CMS
the future of cms, a simple and intuitive content management system ...

ASP.NET MVC Application
best practices like Repository, LINQ, Dapper, Domain objects ...

CFTurbine
cf prototyping engine, generates boilerplate code and views ...

Search Engine LITE
create your own custom search engine for your web site ...

JRun monitor
monitors the memory footprint of JRun engine and auto-restarts a hung engine ...

Validation Library
complete validation library for your web forms ...