Escape Keys - TomdeMan's Blog

Thanks to Oscar and Rob for the quick feedback. Both pointed out flaws that needed addressing immediately. I made the appropriate updates, and after a quick review with Luis, even more.

This release should be as optimized as it gets.

Oscar, indicated the importance of getting the accurate hostname when in a clustered environment. He suggested doing so with:

hostname = CreateObject("java", "java.net.InetAddress").getLocalHost().getHostName();

Which from my research, is the best approach. However, as Rob mentioned in his comment, the idea of creating an object on every exception could create a nasty performance drain. Well, we all know Luis has packed Coldbox with all kinds of goodies, and of course in his 'utilities' plugin he already had a method to getInetHost(), which does exactly what Oscar suggested. Except, since its a CB plugin, its already loaded and cached for us. So I now call a cached object's method when the BugLog plugin initializes and I store it in the instance data.

Next, had to get rid of the CFINVOKE, and not by replacing it with a CreateObject. The best way to do this is with lazy loading. You don't want to create and stash the webservice object in the plugin instance at creation, because CB plugins are initialized with the framework. Lazy loading will create the object the first time it is needed, and will persist as long as the plugin itself exists. Which you can define with the CACHE settings in the plugin metadata.

This is what the latest version looks like:

<cfcomponent hint="Passes Exceptions and Bug Reports to BugLog" extends="coldbox.system.plugin" output="false" cache="true" cachetimeout="20">

   <cffunction name="init" access="public" returntype="BugLog" output="false">
      <cfargument name="controller" type="any" required="true">
      
      <cfset super.Init(arguments.controller) />
      <cfset setPluginName("BugLog")>
      <cfset setPluginVersion("1.2")>
      <cfset setPluginDescription("This is the BugLog plugin.")>
      <cfset setHostName(getPlugin('utilities').getInetHost()) />
      
      <cfreturn this>
   </cffunction>
   
   <!--- creates and logs bug report --->
   <cffunction name="logError" access="public" output="No" returntype="boolean">
      <cfargument name="oExceptionBean" required="true" type="any" />
      <cfargument name="sMessage" required="true" type="string" />
      <cfargument name="sSseverityCode" type="string" default="error" />
      
      <cfparam name="session.cfid" default="" />
      <cfparam name="session.cftoken" default="" />
      
      <cfreturn getBugLogWS().logEntry(
                           dateTime = now(),
                           message = arguments.sMessage,
                           applicationCode = application.applicationname,
                           severityCode = arguments.sSseverityCode,
                           hostName = getHostName(),
                           exceptionMessage = arguments.oExceptionBean.getMessage(),
                           exceptionDetails = arguments.oExceptionBean.getDetail(),
                           CFID = session.CFID,
                           CFTOKEN = session.CFTOKEN,
                           userAgent = cgi.HTTP_USER_AGENT,
                           templatePath = cgi.SCRIPT_NAME,
                           HTMLReport = getController().getExceptionService().renderBugReport(arguments.oExceptionBean)
                           ) />

   </cffunction>
   
   <cffunction name="getBugLogWS" access="public" returntype="any" output="false">
      <cfif not structKeyExists(instance,'oBugLogWS')>
         <cfset setBugLogWS(getPlugin('webservices').getWSobj('BugLog')) />
      </cfif>
      <cfreturn instance.oBugLogWS />
   </cffunction>
   
   <cffunction name="setBugLogWS" access="public" returntype="void" output="false">
      <cfargument name="oBugLogWS" type="any" required="true" />
      <cfset instance.oBugLogWS = arguments.oBugLogWS />
   </cffunction>
   
   <cffunction name="getHostName" access="public" returntype="string" output="false">
      <cfreturn instance.sHostName />
   </cffunction>
   
   <cffunction name="setHostName" access="public" returntype="void" output="false">
      <cfargument name="sHostName" type="string" required="true" />
      <cfset instance.sHostName = arguments.sHostName />
   </cffunction>
   
</cfcomponent>

If you didn't notice, I now allow for you to pass in the Message, and Severity Code, along with the Exception Bean. The code in your exception handler should look something like this:

getPlugin('BugLog',true).logError(
                                 oExceptionBean = exceptionBean,
                                 sMessage = exceptionBean.getMessage(),
                                 sSeverityCode = 'onException');

Hope this helps out, I will be updating the original post. Be sure to check that out if you haven't it contains useful information for those who are just getting this setup.

BugLog and Coldbox Plugin

If you have heard of BugLogHQ, a nice centralized bug reporting application, written by Oscar Arevalo, and you want to integrate it with your Coldbox apps, then this article is for you.

Let's get started...

Be sure to set the Exception Handler in either the Coldbox config or your Environments.xml. For reference, 'main' is my handler and 'onException' is the method or event. By default, the value is blank in the config.

<Setting name="ExceptionHandler"         value="main.onException" />

Next, you need to add the WSDL URL to your Coldbox config file or your Environments.xml.

<Setting name="BugLogWSDL"                   value="http://bugs.mysite.com/listeners/bugLogListenerWS.cfc?wsdl" />

@UPDATE - ** WEBSERVICE PLUGIN UPDATED **

Now, go to that Exception Handler method we defined in the first step. Copy and paste this in there.

@UPDATE - UPDATED CODE HERE

Finally, create the BugLog.cfc and place it in your Plugins directory ('plugins' by default unless you specified otherwise in your CONVENTIONS).

Here's the code.

@UPDATE - UPDATED CODE HERE

That's it.

Now, Coldbox will deliver Bug Reports to the BugLog system, in addition to the internal Bug Reporting setting. If you don't want to use CB to deliver Email Reports then be sure to define that in your config or environments.xml.

<Setting name="EnableBugReports"          value="false" />