Skip to content

Instantly share code, notes, and snippets.

@flexablecoder
Created July 9, 2014 23:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save flexablecoder/718a2ceda2884441c88a to your computer and use it in GitHub Desktop.
Save flexablecoder/718a2ceda2884441c88a to your computer and use it in GitHub Desktop.
This is what I use to manage capturing and sending application errors in my application. hopefully it will be of use to you. **update** There were some questions about this setup. note that there are two files in this solution. The first code section goes in your application.cfc file. the second one is a separate CFC file that you would put with…
<cffunction name="onError" access="public" hint="handle the error" returnType="void" output="true">
<cfargument name="caughtException" type="any" required="false">
<cfsetting requesttimeout="#(GetRequestTimeout() + 10)#"/>
<!--- default settings for issues handled outside of ----->
<cfset local.myException = arguments.caughtException>
<cfset local.fromEmail = "theemailyouwantthissentfrom@somedomain.com">
<cfset local.errorEmail = "theemailyouwanttosendto@yourdomain.com">
<cfset local.catchUtil = createObject("component","Cfcatch").init(local.errorEmail,local.fromEmail)>
<cfset local.mainEvent = "">
<cfset local.applicationname="">
<cfset local.mailSubject = "[cferror] unhandled Exception on #local.applicationName# #cgi.SERVER_NAME# server">
<cfsilent>
<cftry>
<cfif getEnvironment() neq "dev">
<cfset getPageContext().getOut().clearBuffer()>
<cfif isDefined("application.appname")>
<cfset local.applicationName = application.appName>
<cfelseif isdefined("application.applicationName")>
<cfset local.applicationName = application.applicationName>
<cfelse>
<cfset local.applicationName = "unknown">
</cfif>
<cfif isDefined("local.myException.message")>
<cfset local.mailSubject = "[cferror] #local.myException.message# on #local.applicationName# #cgi.SERVER_NAME#">
</cfif>
<cfif isObject(local.myException) and isObject(local.catchUtil)>
<cfset local.catchUtil.sendError(catchobj=local.myException,
mailSubject=local.mailSubject,
mailText="Generally this is an error that happened somewhere in the code and was not able
to be handled by the regular code.")>
<cfelse>
<cfset local.catchUtil.sendError(mailSubject=local.mailsubject,
mailText="Could not include a catch dump, here is everything that could be put together.
for some reason the regular dump of the local. failed, so this is a back up email in an effort
to make sure we get all the issues resolved.
this is likely caused by a timeout, but we didn't get an event")>
</cfif>
</cfif>
<cfcatch type="any">
<cfset local.catchUtil.sendError(catchobj=cfcatch,
mailSubject=local.mailsubject,
mailText="Something happened when trying to send a dump of the original catch.
this is a backup message to inform you of a truly unhandled error.
The dump included is not the original catch information,
it is the catch information from what went wrong in the error message reporting")>
</cfcatch>
</cftry>
</cfsilent>
<!--- this rethrows the exception out to the main error handling page. ---->
<cfif getEnvironment() neq "dev">
<Cfthrow object="#local.myException#">
<cfelse>
<cfdump var="#local.myException#">
<cfabort>
</cfif>
</cffunction>
<cffunction name="GetRequestTimeout" access="public" returntype="numeric" output="false" hint="Returns the current request timeout for the current page page request.">
<!--- Define the local scope. --->
<cfset var LOCAL = StructNew() />
<!--- Get the request monitor. --->
<cfset LOCAL.RequestMonitor = CreateObject("java","coldfusion.runtime.RequestMonitor" ) />
<!--- Return the current request timeout. --->
<cfreturn LOCAL.RequestMonitor.GetRequestTimeout() />
</cffunction>
<cffunction name="getEnvironment" access="private" output="false" returntype="string">
<Cfscript>
local.cleanedHost = cleanDomain(cgi.HTTP_HOST);
// this won't run unless you set the application
if ( structKeyExists(application,"devServers") and structKeyExists(application,"qaServers")) {
if (isSimpleValue(application.devservers) and listFindNoCase(application.devServers,local.cleanedHost) gt 0) {
// remove this code after switch over to array is completed.
return "dev";
} else if (isSimpleValue(application.qaServers) and listFindNoCase(application.qaServers,local.cleanedHost) gt 0) {
return "QA";
} else if ( arrayFindNoCase(application.devservers,local.cleanedHost) gt 0) {
return "dev";
} else if (arrayfindNocase(application.qaservers,local.cleanedHost) gt 0) {
return "qa";
} else {
return "prod";
}
} else {
return "prod";
}
</Cfscript>
</cffunction>
<cfcomponent>
<cffunction name="init" output="no" returnType="cfcatch" access="public">
<cfargument name="mailTo" required="no" default="" type="string" />
<cfargument name="mailFrom" required="no" default="" type="string" />
<cfscript>
this.mailTo = arguments.mailTo;
this.mailFrom = arguments.mailFrom;
return this;
</cfscript>
</cffunction>
<cffunction name="throw" output="no" returnType="void" access="public">
<cfargument name="message" required="yes" type="string" />
<cfargument name="detail" required="no" default="" type="string" />
<cfthrow message="#arguments.message#" detail="#arguments.detail#" />
</cffunction>
<cffunction name="showErrorAndAbort" output="yes" returnType="void" access="public">
<cfargument name="cfcatch" type="any" required="yes" />
<cfargument name="msg" type="any" required="no" default="error" />
<cfdump expand="false" var="#cfcatch#" label="#arguments.msg#"><cfabort showerror="#cfcatch.Message#">
</cffunction>
<cffunction name="sendError" output="no" returnType="boolean" access="public">
<cfargument name="catchobj" type="any" required="false" />
<cfargument name="mailSubject" type="string" required="false" default="Error Report" />
<cfargument name="mailText" type="string" required="false" default="" />
<cfargument name="extraDump" type="any" required="false" default="" />
<cfset var tagIndex = ''>
<Cfset var key="">
<cfset var mailcontent = "">
<cfparam name="arguments.catchobj" default="#structnew()#">
<cfparam name="arguments.catchobj.message" default="" type="string" />
<cfparam name="arguments.catchobj.detail" default="" type="string" />
<cfparam name="arguments.catchobj.tagContext" default="#arrayNew(1)#" />
<cfparam name="arguments.catchobj.cause" default="#structnew()#">
<cfparam name="arguments.catchobj.rootcause" default="#structnew()#">
<!------ suppress mailto if there is no email. ----->
<cfsavecontent variable="mailcontent">
<cfoutput>
<br>
<p>#arguments.mailText#</p>
<hr>
<cfif isdefined("arguments.catchobj") and isObject(arguments.catchobj)>
<span style="font: normal 600 16pt Calibri, Arial, sans-serif; color: ##57a">Exception Data</span>
<br/>
<p>
<table>
<Tr><td style="background-color: ##F7F1D0; BORDER: ##ccc 1px dotted; margin:0px; padding: 2px; font: normal 700 10pt Tahoma, san-serif; color: ##555;">Message:</td>
<td style="BORDER: ##ccc 1px dotted; margin:0px; padding: 5px; font: normal 400 9pt Tahoma, san-serif; color: ##555;"><cfif structKeyExists(arguments.catchobj,"message")>#arguments.catchobj.message#</cfif></td>
</Tr>
<tr><td style="background-color: ##F7F1D0; BORDER: ##ccc 1px dotted; margin:0px; padding: 2px; font: normal 700 10pt Tahoma, san-serif; color: ##555;">Detail:</td>
<td style="BORDER: ##ccc 1px dotted; margin:0px; padding: 5px; font: normal 400 9pt Tahoma, san-serif; color: ##555;"><cfif structKeyExists(arguments.catchobj,"detail")>#arguments.catchobj.detail#</cfif></td>
</tr>
<tr><td style="background-color: ##F7F1D0; BORDER: ##ccc 1px dotted; margin:0px; padding: 2px; font: normal 700 10pt Tahoma, san-serif; color: ##555;">Type:</Td>
<td style="BORDER: ##ccc 1px dotted; margin:0px; padding: 5px; font: normal 400 9pt Tahoma, san-serif; color: ##555;"><cfif structKeyExists(arguments.catchobj,"type")>#arguments.catchobj.type#</cfif></td>
</tr>
<tr><td style="background-color: ##F7F1D0; BORDER: ##ccc 1px dotted; margin:0px; padding: 2px; font: normal 700 10pt Tahoma, san-serif; color: ##555;">Extended info:</Td>
<td style="BORDER: ##ccc 1px dotted; margin:0px; padding: 5px; font: normal 400 9pt Tahoma, san-serif; color: ##555;"><cfif structKeyExists(arguments.catchobj,"extendedInfo")>#arguments.catchobj.extendedInfo#</cfif></td>
</tr>
<tr><td style="background-color: ##F7F1D0; BORDER: ##ccc 1px dotted; margin:0px; padding: 2px; font: normal 700 10pt Tahoma, san-serif; color: ##555;">Error Code:</Td>
<td style="BORDER: ##ccc 1px dotted; margin:0px; padding: 5px; font: normal 400 9pt Tahoma, san-serif; color: ##555;"><cfif structKeyExists(arguments.catchobj,"errorcode")>#arguments.catchobj.errorCode#</cfif></td>
</tr>
</table>
</p>
<cfif StructKeyExists(arguments.catchobj,"tagContext") AND isArray(arguments.catchobj.tagContext)>
<span style="font: normal 600 16pt Calibri, Arial, sans-serif; color: ##57a">Error Location</span><br />
<pre style="BORDER: ##ccc 1px dotted; margin:0px; padding: 5px; font: normal 400 9pt Tahoma, san-serif; color: ##555; background-color:##F7F1D0"><!---
--->#lJustify("Line", 5)# Template#chr(10)#<!---
---><cfloop from="1" to="#arrayLen(arguments.catchobj.tagContext)#" step="1" index="tagIndex"><!---
--->#lJustify(arguments.catchobj.tagContext[tagIndex].line, 5)# #arguments.catchobj.tagContext[tagIndex].template##chr(10)#<!---
---></cfloop></pre>
</cfif>
<cfif StructKeyExists(arguments.catchobj,"cause") AND isStruct(arguments.catchobj.cause) and not structIsempty(arguments.catchobj.cause)>
#dumpStruct(structtoDump=arguments.catchobj.cause,
sectionName="Cause Information",
omitKeys="",
recurseLevels=0)#
</cfif>
<cfif StructKeyExists(arguments.catchobj,"rootcause") AND isStruct(arguments.catchobj.rootcause) and not structIsempty(arguments.catchobj.rootcause)>
#dumpStruct(structtoDump=arguments.catchobj.rootcause,
sectionName="Root Cause Information",
omitKeys="",
recurseLevels=0)#
</cfif>
</cfif>
<cfif isStruct(arguments.extraDump) AND NOT StructIsEmpty(arguments.extraDump)>
#dumpStruct(structtoDump=arguments.extraDump,
sectionName="Extra dump information",
recurseLevels=2)#
</cfif>
<cfif isDefined("URL") AND StructCount(URL) gt 0>
#dumpStruct(structtoDump=url,
sectionName="URL Data",
omitKeys="CFID,CFToken",
recurseLevels=0)#
</cfif>
<cfif isDefined("FORM") and structCount(form) gt 0>
#dumpStruct(structtoDump=form,
sectionName="FORM Data",
omitKeys="fieldNames",
recurseLevels=0)#
</cfif>
<cfif isDefined('session')>
#dumpStruct(structtoDump=session,
sectionName="SESSION Data",
omitKeys="",
recurseLevels=1)#
</cfif>
<cfif isDefined("CGI")>
#dumpStruct(structtoDump=cgi,
sectionName="CGI Data",
omitKeys="fieldNames",
recurseLevels=0)#
</cfif>
</cfoutput>
</cfsavecontent>
<cfif len(trim(this.mailTo)) gt 0>
<cftry>
<cfmail to="#this.mailTo#" from="#this.mailFrom#" subject="#arguments.mailSubject#" type="html">
#mailcontent#
</cfmail>
<cfcatch type="any">
<cflog type="error" text="Could not send message for #arguments.mailSubject#">
</cfcatch>
</cftry>
</cfif>
<cfreturn true />
</cffunction>
<cffunction name="dumpStruct" access="private" output="false" returntype="string">
<cfargument name="structToDump" required="false" default="#structNew()#">
<cfargument name="sectionName" required="false" default="" type="string">
<cfargument name="omitkeys" required="false" default="" type="string" >
<cfargument name="recurseLevels" required="false" default="0" type="numeric">
<cfset var returnString = "">
<Cfset var key="">
<cfsavecontent variable="returnString">
<cfif len(trim(arguments.sectionName)) gt 0>
<p><span style="font: normal 600 16pt Calibri, Arial, sans-serif; color: #5577aa;">
<cfoutput>#arguments.sectionName#</cfoutput></span>
</cfif>
<table style="border: 1px solid 879eba; margin: 0; padding: 0;">
<cfloop list="#StructKeyList(arguments.structToDump)#" index="key">
<cfif not listfindnocase(arguments.omitkeys,key)>
<tr>
<cfoutput>
<td style="background-color: ##d8dee5; BORDER: ##ccc 1px dotted; margin:0px; padding: 2px; font: normal 700 10pt Tahoma, san-serif; color: ##555;">#KEY#</td>
<td style="BORDER: ##ccc 1px dotted; margin:0px; padding: 5px; font: normal 400 9pt Tahoma, san-serif; color: ##555;">
<cfif isSimpleValue(arguments.structToDump[key])>#arguments.structToDump[KEY]#
<cfelseif isStruct(arguments.structToDump[key]) and (arguments.recurseLevels-1) gte 0>
#dumpStruct(structtoDump=arguments.structTodump[key],
sectionName="",
omitKeys=arguments.omitkeys,
recurseLevels=arguments.recurseLevels-1)#
<cfelse>[complex value]
</cfif>
</td>
</cfoutput>
</tr>
</cfif>
</cfloop>
</table>
</cfsavecontent>
<cfreturn returnString>
</cffunction>
</cfcomponent>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment