Created
July 9, 2014 23:45
-
-
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…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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