├── examples ├── readme.txt ├── CFWheels │ ├── readme.txt │ ├── Hoth │ │ ├── .gitignore │ │ ├── db │ │ │ └── .gitignore │ │ ├── logs │ │ │ └── .gitignore │ │ ├── object │ │ │ └── .gitignore │ │ └── ReadMe.txt │ ├── config │ │ ├── .gitignore │ │ └── HothConfig.cfc │ ├── events │ │ ├── .gitignore │ │ ├── onrequeststart.cfm │ │ └── onerror.cfm │ └── views │ │ └── hoth │ │ ├── error.cfm │ │ └── report.cfm ├── ColdBox │ ├── readme.txt │ └── HothReportEventHandler.cfc ├── FarCry │ └── farcryhoth │ │ ├── packages │ │ ├── custom │ │ │ └── hoth │ │ │ │ └── _readme.txt │ │ └── forms │ │ │ └── configHoth.cfc │ │ ├── www │ │ ├── Application.cfc │ │ └── facade │ │ │ └── reporting.cfc │ │ ├── customadmin │ │ ├── hoth.cfm │ │ └── farcryhoth.xml │ │ ├── install │ │ └── manifest.cfc │ │ ├── README │ │ └── config │ │ └── _serverSpecificVarsAfterInit.cfm ├── Example_Logs │ ├── incidents │ │ ├── 049000E8B1A24DA94AD81BB289977551ECFA16FC.log │ │ ├── 00422207A2688146A6D66DDAA034AC2B8D9F2DEA.log │ │ └── 02E9D2BB4A77C0AA0EB521E376470603CEB6BC8B.log │ └── exceptions │ │ ├── 049000E8B1A24DA94AD81BB289977551ECFA16FC.log │ │ ├── 00422207A2688146A6D66DDAA034AC2B8D9F2DEA.log │ │ └── 02E9D2BB4A77C0AA0EB521E376470603CEB6BC8B.log ├── blogPost │ ├── SimpleHothIntegration.txt │ ├── TrappedErrors.txt │ ├── ColdBox.txt │ ├── RecomendedApplicationCFC.txt │ ├── HothReporter.cfc │ ├── HothConfig.cfc │ └── ImplementReportingWithColdBox.txt └── ColdFusion │ └── HothReportUI.cfc ├── db ├── .gitignore ├── readme.txt └── applications.hoth ├── test ├── logs │ └── .gitignore ├── facade │ └── RemoteFacade.cfc ├── Application.cfc ├── unit │ ├── HothConfigTest.cfc │ ├── HothReporterTest.cfc │ ├── HothApplicationManagerTest.cfc │ └── HothTrackerTest.cfc └── HothConfig.cfc ├── .gitignore ├── logs └── readme.txt ├── Application.cfc ├── object ├── iHothConfig.cfc ├── HothTime.cfc ├── CoreConfig.cfc └── HothApplicationManager.cfc ├── Report.cfc ├── extras └── ColdBoxInterceptor.cfc ├── config └── HothConfig.cfc ├── HothReporter.cfc ├── README.txt ├── views └── report.html └── HothTracker.cfc /examples/readme.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /db/.gitignore: -------------------------------------------------------------------------------- 1 | /*.hoth 2 | -------------------------------------------------------------------------------- /examples/CFWheels/readme.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/ColdBox/readme.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/CFWheels/Hoth/.gitignore: -------------------------------------------------------------------------------- 1 | #nothing here -------------------------------------------------------------------------------- /examples/CFWheels/config/.gitignore: -------------------------------------------------------------------------------- 1 | #nothing here -------------------------------------------------------------------------------- /examples/CFWheels/events/.gitignore: -------------------------------------------------------------------------------- 1 | #nothing here -------------------------------------------------------------------------------- /examples/CFWheels/Hoth/db/.gitignore: -------------------------------------------------------------------------------- 1 | #nothing here -------------------------------------------------------------------------------- /examples/CFWheels/Hoth/logs/.gitignore: -------------------------------------------------------------------------------- 1 | #nothing here -------------------------------------------------------------------------------- /examples/CFWheels/Hoth/object/.gitignore: -------------------------------------------------------------------------------- 1 | #nothing here -------------------------------------------------------------------------------- /test/logs/.gitignore: -------------------------------------------------------------------------------- 1 | /incidents 2 | /exceptions 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.project 2 | /settings.xml 3 | /.settings 4 | -------------------------------------------------------------------------------- /examples/FarCry/farcryhoth/packages/custom/hoth/_readme.txt: -------------------------------------------------------------------------------- 1 | Hoth files go here -------------------------------------------------------------------------------- /examples/Example_Logs/incidents/049000E8B1A24DA94AD81BB289977551ECFA16FC.log: -------------------------------------------------------------------------------- 1 | {ts '2011-01-21 02:09:11'} -------------------------------------------------------------------------------- /examples/FarCry/farcryhoth/www/Application.cfc: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /logs/readme.txt: -------------------------------------------------------------------------------- 1 | This is the default location for Hoth logs. 2 | 3 | You should provide a better location in your Hoth Config object that 4 | is unique to your application. 5 | -------------------------------------------------------------------------------- /db/readme.txt: -------------------------------------------------------------------------------- 1 | This folder is populated by Hoth to keep track of all applications that 2 | use this instance of Hoth so Hoth can find the log files for your 3 | applications when generating reports. -------------------------------------------------------------------------------- /db/applications.hoth: -------------------------------------------------------------------------------- 1 | [{"logPath":"\/Hoth\/test\/logs","applicationName":"HothUnitTests","created":1298051472},{"logPath":"runtime\/logs","applicationName":"ATV4","created":"November, 13 2012 18:44:28"}] -------------------------------------------------------------------------------- /examples/CFWheels/Hoth/ReadMe.txt: -------------------------------------------------------------------------------- 1 | Place the Hoth files here. 2 | 3 | === file/folder structure 4 | -Hoth 5 | HothReporter.cfc 6 | HothTracker.cfc 7 | --db folder 8 | --logs folder 9 | --objects folder 10 | -------------------------------------------------------------------------------- /examples/Example_Logs/incidents/00422207A2688146A6D66DDAA034AC2B8D9F2DEA.log: -------------------------------------------------------------------------------- 1 | {ts '2011-02-11 04:43:23'} 2 | {ts '2011-02-11 04:44:23'} 3 | {ts '2011-02-11 04:45:23'} 4 | {ts '2011-02-11 04:46:23'} 5 | {ts '2011-02-11 04:47:23'} -------------------------------------------------------------------------------- /examples/CFWheels/views/hoth/error.cfm: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /examples/Example_Logs/incidents/02E9D2BB4A77C0AA0EB521E376470603CEB6BC8B.log: -------------------------------------------------------------------------------- 1 | {ts '2011-02-18 06:57:17'} {ts '2011-02-18 06:57:48'} {ts '2011-02-18 06:57:48'} {ts '2011-02-18 06:57:48'} {ts '2011-02-18 06:57:48'} {ts '2011-02-18 06:57:48'} 2 | -------------------------------------------------------------------------------- /Application.cfc: -------------------------------------------------------------------------------- 1 | 5 | 6 | -------------------------------------------------------------------------------- /examples/FarCry/farcryhoth/customadmin/hoth.cfm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | #application.hoth.report.getReportView()# 9 | 10 | -------------------------------------------------------------------------------- /test/facade/RemoteFacade.cfc: -------------------------------------------------------------------------------- 1 | /** 2 | Aaron Greenlee 3 | http://aarongreenlee.com/ 4 | 5 | This work is licensed under a Creative Commons Attribution-Share-Alike 3.0 6 | Unported License. 7 | 8 | // Original Info ----------------------------------------------------------- 9 | Author : Aaron Greenlee 10 | Created : 10/01/2010 11 | 12 | MXUnit Remote Facade 13 | 14 | */ 15 | component extends='mxunit.framework.RemoteFacade' {} -------------------------------------------------------------------------------- /examples/CFWheels/events/onrequeststart.cfm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | // Place Hoth into Application Memory. 5 | if (!structKeyExists(application, 'HothTracker')) 6 | { 7 | application.HothTracker = 8 | new Hoth.HothTracker( new config.HothConfig() ); 9 | } 10 | 11 | // anything you need here... 12 | 13 | return true; 14 | -------------------------------------------------------------------------------- /test/Application.cfc: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/FarCry/farcryhoth/customadmin/farcryhoth.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 |
10 |
-------------------------------------------------------------------------------- /examples/blogPost/SimpleHothIntegration.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/FarCry/farcryhoth/install/manifest.cfc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /object/iHothConfig.cfc: -------------------------------------------------------------------------------- 1 | /** 2 | Aaron Greenlee 3 | http://aarongreenlee.com/ 4 | 5 | This work is licensed under a Creative Commons Attribution-Share-Alike 3.0 6 | Unported License. 7 | 8 | // Original Info ----------------------------------------------------------- 9 | Author : Aaron Greenlee 10 | Created : 10/01/2010 11 | 12 | Interface for a Hoth Config Object. 13 | 14 | */ 15 | interface { 16 | public function init (); 17 | public string function getLogPathExpanded(); 18 | public string function getPath (name); 19 | } -------------------------------------------------------------------------------- /examples/FarCry/farcryhoth/www/facade/reporting.cfc: -------------------------------------------------------------------------------- 1 | component output="false" { 2 | 3 | remote function index() output="false" returntype="string" returnformat="plain" { 4 | return application.hoth.report.getReportView(application.hoth.config); 5 | } 6 | 7 | remote function report(string exception = 'all') output="false" returntype="struct" returnformat="json" { 8 | return application.hoth.report.report(exception = arguments.exception); 9 | } 10 | 11 | remote function delete(string exception = 'all') output="false" returntype="array" returnformat="json" { 12 | return application.hoth.report.delete(exception = arguments.exception); 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /examples/blogPost/TrappedErrors.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /object/HothTime.cfc: -------------------------------------------------------------------------------- 1 | component 2 | { 3 | /** 4 | * Returns the number of seconds since UTC January 1, 1970, 00:00:00 5 | * (Epoch time). 6 | * 7 | * @param DateTime Date/time object you want converted to 8 | * Epoch time.(Required) 9 | * 10 | * @return Returns a numeric value. 11 | * @author Rob Brooks-Bilson (rbils@amkor.com) 12 | * @version 1, June 21, 2002 13 | */ 14 | function GetEpochTimeFromLocal() { 15 | local.datetime = 0; 16 | 17 | if ( arrayLen(arguments) == 0) 18 | { 19 | local.datetime = Now(); 20 | } else { 21 | local.datetime = arguments[1]; 22 | } 23 | 24 | return 25 | DateDiff( 26 | "s" 27 | ,DateConvert("utc2Local", "January 1 1970 00:00") 28 | ,datetime); 29 | } 30 | } -------------------------------------------------------------------------------- /examples/FarCry/farcryhoth/README: -------------------------------------------------------------------------------- 1 | FarCry plugin for the Hoth Exception Reporting framework. 2 | Hoth was created by Aaron Greenlee 3 | http://aarongreenlee.com/share/hoth-coldfusion-errors-tracking-reporting 4 | 5 | FarCry plugin created by Sean Coyne (sean@n42designs.com) 6 | 7 | This is an example of the farcryhoth FarCry plugin. You can find the latest version of this plugin at https://github.com/seancoyne/farcryhoth 8 | 9 | I suggest you use the latest version of the plugin, however, if you want to use this version of the plugin, you need to place a copy of Hoth in 10 | the farcryhoth/packages/custom/hoth directory. You will also want to follow the installation instructions at: 11 | https://github.com/seancoyne/farcryhoth/blob/master/README -------------------------------------------------------------------------------- /examples/CFWheels/events/onerror.cfm: -------------------------------------------------------------------------------- 1 | 2 | 3 | // Create an instance of Hoth if one does not exist in the 4 | // application scope. Hoth should exist in the Application Scope 5 | // but, if something went wrong there we are ensured tracking. 6 | arguments.Except = arguments.exception; 7 | arguments.EventName = arguments.eventName; 8 | local.HothTracker = (structKeyExists(application, 'HothTracker')) 9 | ? application.HothTracker 10 | : new Hoth.HothTracker( new config.HothConfig() ); 11 | 12 | local.HothTracker.track(Except); 13 | 14 | 15 |

Error!

16 |

17 | Sorry, that caused an unexpected error.
18 | Please try again later. 19 |

-------------------------------------------------------------------------------- /examples/blogPost/ColdBox.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | local.HothTracker = (structKeyExists(application, 'HothTracker')) 6 | ? application.HothTracker 7 | : new Hoth.HothTracker( new atv.config.HothConfig() ); 8 | 9 | try { 10 | //Grab Exception From request collection, placed by ColdBox 11 | local.ExceptionBean = Event.getValue("ExceptionBean"); 12 | } catch (any e) { 13 | // Record that the exception bean was not found! 14 | // This should also provide the context of the original error 15 | // however, the error details will be different. This is important 16 | // in the event ColdBox has an issue capturing the error. 17 | local.HothTracker.track(e); 18 | 19 | return; 20 | } 21 | 22 | local.HothTracker.track(local.ExceptionBean); 23 | 24 | -------------------------------------------------------------------------------- /test/unit/HothConfigTest.cfc: -------------------------------------------------------------------------------- 1 | /** 2 | Aaron Greenlee 3 | http://aarongreenlee.com/ 4 | 5 | This work is licensed under a Creative Commons Attribution-Share-Alike 3.0 6 | Unported License. 7 | 8 | // Original Info ----------------------------------------------------------- 9 | Author : Aaron Greenlee 10 | Created : 12/13/2010 10:17:31 AM 11 | 12 | Unit Test for Hoth Config Object. 13 | 14 | // Modifications :--------------------------------------------------------- 15 | 16 | */ 17 | 18 | /** Unit test for Hoth.HothTracker */ 19 | component extends="mxunit.framework.TestCase" 20 | { 21 | 22 | /** Constructor */ 23 | public void function setUp() 24 | { 25 | // Load our test config 26 | HothConfig = new Hoth.test.HothConfig(); 27 | 28 | return; 29 | } 30 | 31 | // ------------------------------------------------------------------------- 32 | public void function Confirm_Default_Storage() { 33 | // Confirm the global settings themselves 34 | assertEquals( 35 | '/Hoth/db/' 36 | ,HothConfig.getGlobalDatabasePath() 37 | ,'Has the default location to store application knowledge changed?' 38 | ); 39 | 40 | return; 41 | } 42 | } -------------------------------------------------------------------------------- /examples/blogPost/RecomendedApplicationCFC.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | // Place Hoth into Application Memory. 5 | if (!structKeyExists(application, 'HothTracker')) { 6 | 7 | lock 8 | name="#application.ApplicationName#_HothTracker" 9 | type="exclusive" 10 | timeout="10" { 11 | 12 | if (!structKeyExists(application, 'HothTracker')) { 13 | application.HothTracker = new Hoth.HothTracker( new config.HothConfig() ); 14 | } 15 | 16 | } 17 | } 18 | 19 | // anything you need here... 20 | 21 | return true; 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | // Create an instance of Hoth if one does not exist in the 30 | // application scope. Hoth should exist in the Application Scope 31 | // but, if something went wrong there we are ensured tracking. 32 | local.HothTracker = (structKeyExists(application, 'HothTracker')) 33 | ? application.HothTracker 34 | : new Hoth.HothTracker( new config.HothConfig() ); 35 | 36 | local.HothTracker.track(Except); 37 | 38 | // anything you need here... 39 | 40 | 41 | -------------------------------------------------------------------------------- /test/HothConfig.cfc: -------------------------------------------------------------------------------- 1 | /** 2 | Aaron Greenlee 3 | http://aarongreenlee.com/ 4 | 5 | This work is licensed under a Creative Commons Attribution-Share-Alike 3.0 6 | Unported License. 7 | 8 | // Original Info ----------------------------------------------------------- 9 | Author : Aaron Greenlee 10 | Created : 10/01/2010 11 | 12 | Unit Test Config for Hoth 13 | 14 | // Modifications :--------------------------------------------------------- 15 | Modified : 12/13/2010 9:52:41 AM by Aaron Greenlee. 16 | - Now supporting ColdBox 3.0 RC1 17 | Modified : 02/18/2011 1:20:12 PM by Aaron Greenlee. 18 | - Now supporting the HothReportURL value. 19 | */ 20 | component 21 | implements='Hoth.object.iHothConfig' 22 | extends='Hoth.object.CoreConfig' 23 | accessors=true { 24 | 25 | property name='applicationName' default='HothUnitTests'; 26 | property name='timeToLock' default='1'; 27 | property name='logPath' default='/Hoth/test/logs'; 28 | property name='EmailNewExceptions' default='true'; 29 | property name='EmailNewExceptionsTo' default='aarongreenlee@gmail.com'; 30 | property name='EmailNewExceptionsFrom' default='aarongreenlee@gmail.com'; 31 | property name='EmailNewExceptionsFile' default='true'; 32 | property name='HothReportURL' default='UNIT_TEST_WILL_POPULATE'; 33 | 34 | public function init () 35 | { 36 | super.init(); 37 | return this; 38 | } 39 | } -------------------------------------------------------------------------------- /test/unit/HothReporterTest.cfc: -------------------------------------------------------------------------------- 1 | /** 2 | Aaron Greenlee 3 | http://aarongreenlee.com/ 4 | 5 | This work is licensed under a Creative Commons Attribution-Share-Alike 3.0 6 | Unported License. 7 | 8 | // Original Info ----------------------------------------------------------- 9 | Author : Aaron Greenlee 10 | Created : 02/18/2011 11 | 12 | Unit Test for HothReporter 13 | 14 | // Modifications :--------------------------------------------------------- 15 | */ 16 | 17 | import coldbox.system.testing.*; 18 | 19 | /** Unit test for Hoth.HothTracker */ 20 | component extends="mxunit.framework.TestCase" { 21 | 22 | /** Constructor */ 23 | public void function setUp() { 24 | MockBox = new MockBox(); 25 | 26 | // Load our test config 27 | UnitTestHothConfig = new Hoth.test.HothConfig(); 28 | UnitTestHothConfig.setHothReportURL('UNIT_TEST_EXPECTED_VALUE'); 29 | 30 | // SUT 31 | SUT = new Hoth.HothReporter(UnitTestHothConfig); 32 | 33 | return; 34 | } 35 | 36 | // ------------------------------------------------------------------------------ 37 | /** Test default ColdFusion exception tracking. */ 38 | public void function getReportView() { 39 | 40 | local.view = SUT.getReportView(); 41 | writeDump(var=local.view,output='c:\web\debug.log'); 42 | 43 | local.position = find('UNIT_TEST_EXPECTED_VALUE',local.view,1); 44 | 45 | assert( 46 | local.position > 0 47 | ,'The configured URL was not inserted within the report HTML.' 48 | ); 49 | return; 50 | } 51 | } -------------------------------------------------------------------------------- /examples/blogPost/HothReporter.cfc: -------------------------------------------------------------------------------- 1 | // This CFC offers no protection--thus, anyone can access this. 2 | // You can implement this by renaming the CFC with a UUID--that can secure 3 | // this through obscurity. But, I prefer the approach shown in the ColdBox 4 | // example. That is what I use. I have not tried this code :( 5 | 6 | component 7 | { 8 | /** Loads the Web UI (HTML) **/ 9 | remote function index () returnformat='plain' { 10 | local.HothReport = new Hoth.HothReporter( new config.HothConfig() ); 11 | return local.HothReport.getReportView(); 12 | } 13 | 14 | /** Access Hoth report data as JSON. 15 | @exception If not provided a list of exceptions will be returned. 16 | If provided, the value should be an exception hash which 17 | modified the behavior to return information for only 18 | that exception. **/ 19 | remote function report (string exception) returnformat='JSON' { 20 | local.report = (structKeyExists(arguments, 'exception') 21 | ? arguments.exception 22 | : 'all'); 23 | 24 | local.HothReport = new Hoth.HothReporter( new config.HothConfig() ); 25 | return local.HothReport.report(local.report); 26 | } 27 | 28 | /** Delete a report. **/ 29 | remote function delete (string exception)returnformat='JSON' { 30 | if (!structKeyExists(arguments, 'exception')) 31 | { 32 | // We can delete all exceptions at once! 33 | arguments.exception = 'all'; 34 | } 35 | 36 | local.HothReport = new Hoth.HothReporter( new config.HothConfig() ); 37 | 38 | // Delete! 39 | return local.HothReporter.delete(arguments.exception); 40 | } 41 | } -------------------------------------------------------------------------------- /Report.cfc: -------------------------------------------------------------------------------- 1 | // This CFC offers no protection--thus, anyone can access this. 2 | // You can implement this by renaming the CFC with a UUID--that can secure 3 | // this through obscurity. But, I prefer the approach shown in the ColdBox 4 | // example. That is what I use. I have not tried this code :( 5 | 6 | component 7 | { 8 | /** Loads the Web UI (HTML) **/ 9 | remote function index () returnformat='plain' { 10 | local.HothReport = new Hoth.HothReporter( new config.HothConfig() ); 11 | return local.HothReport.getReportView(); 12 | } 13 | 14 | /** Access Hoth report data as JSON. 15 | @exception If not provided a list of exceptions will be returned. 16 | If provided, the value should be an exception hash which 17 | modified the behavior to return information for only 18 | that exception. **/ 19 | remote function report (string exception) returnformat='JSON' { 20 | local.report = (structKeyExists(arguments, 'exception') 21 | ? arguments.exception 22 | : 'all'); 23 | 24 | local.HothReport = new Hoth.HothReporter( new config.HothConfig() ); 25 | return local.HothReport.report(local.report); 26 | } 27 | 28 | /** Delete a report. **/ 29 | remote function delete (string exception)returnformat='JSON' { 30 | if (!structKeyExists(arguments, 'exception')) 31 | { 32 | // We can delete all exceptions at once! 33 | arguments.exception = 'all'; 34 | } 35 | 36 | local.HothReport = new Hoth.HothReporter( new config.HothConfig() ); 37 | 38 | // Delete! 39 | return local.HothReporter.delete(arguments.exception); 40 | } 41 | } -------------------------------------------------------------------------------- /examples/FarCry/farcryhoth/packages/forms/configHoth.cfc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /examples/FarCry/farcryhoth/config/_serverSpecificVarsAfterInit.cfm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /examples/ColdBox/HothReportEventHandler.cfc: -------------------------------------------------------------------------------- 1 | /** 2 | Example Event Handler to report Hoth exceptions from within your 3 | existing ColdBox application. To use this, just set up the following route. 4 | 5 | addRoute(pattern = 'hoth/:action?' 6 | ,handler = 'HothReportEventHandler'); 7 | */ 8 | 9 | component { 10 | 11 | public void function preHandler(required Event) 12 | { 13 | var rc = Event.getCollection(); 14 | var prc = Event.getCollection(private=true); 15 | 16 | // Only allow access to this report if we are 17 | // in debug mode. 18 | if (!getDebugMode()) 19 | { 20 | setNextEvent('home'); 21 | } 22 | 23 | // This line assumes you have your HothConfig within the config 24 | // directory of your ColdBox application. 25 | prc.HothReporter = new Hoth.HothReporter( new config.HothConfig() ); 26 | } 27 | 28 | 29 | public void function index (required Event) { 30 | var rc = Event.getCollection(); 31 | var prc = Event.getCollection(private=true); 32 | 33 | Event.setView(name='site/hoth',noLayout=true); 34 | Event.renderData(type='html',data=prc.HothReporter.getReportView()); 35 | 36 | return; 37 | } 38 | public void function report (required Event) { 39 | var rc = Event.getCollection(); 40 | var prc = Event.getCollection(private=true); 41 | 42 | local.report = (structKeyExists(rc, 'exception') 43 | ? rc.exception 44 | : 'all'); 45 | 46 | Event.renderData(type='json',data=prc.HothReporter.report(local.report)); 47 | 48 | return; 49 | } 50 | public void function delete (required Event) { 51 | var rc = Event.getCollection(); 52 | var prc = Event.getCollection(private=true); 53 | 54 | if (!structKeyExists(rc, 'exception')) 55 | { 56 | rc.exception = 'all'; 57 | } 58 | 59 | local.result = prc.HothReporter.delete(rc.exception); 60 | 61 | Event.renderData(type='json',data=local.result); 62 | return; 63 | } 64 | } -------------------------------------------------------------------------------- /examples/CFWheels/config/HothConfig.cfc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Aaron Greenlee 3 | * 4 | *

Description

5 | * An example configuration object for your appication. 6 | * Customize this configuration object for your needs. 7 | * 8 | * Created 9 | * 2/9/2011 10:22:19 AM 10 | * 11 | * @author Aaron Greenlee 12 | * @version 1 13 | * @see N/A 14 | **/ 15 | 16 | component 17 | implements = 'Hoth.object.iHothConfig' 18 | extends = 'Hoth.object.CoreConfig' 19 | accessors = true 20 | { 21 | 22 | /** What is the name of your application? */ 23 | property 24 | name='applicationName' 25 | default='Amazing ColdFusion Club 3'; 26 | 27 | /** How many seconds should we lock file operations? 28 | For most operations this is exclusive to a unique exception. */ 29 | property 30 | name='timeToLock' 31 | default='1'; 32 | 33 | /** Where would you like Hoth to save exception data? 34 | This folder should be empty. */ 35 | property 36 | name='logPath' 37 | default='/Hoth/logs'; 38 | 39 | // ------------------------------------------------------------------------------ 40 | /** Would you like new exceptions to be emailed to you? */ 41 | property 42 | name='EmailNewExceptions' 43 | default='true'; 44 | 45 | /** What address(es) should receive these e-mails? */ 46 | property 47 | name='EmailNewExceptionsTo' 48 | default='you@email.com;co-worker@email.com'; 49 | 50 | /** What address would you like these emails sent from? */ 51 | property 52 | name='EmailNewExceptionsFrom' 53 | default='you@email.com'; 54 | 55 | /** Would you like the raw JSON attached to the e-mail? */ 56 | property 57 | name='EmailNewExceptionsFile' 58 | default='true'; 59 | // ------------------------------------------------------------------------------ 60 | 61 | /** 62 | The mapping where you would like Hoth to write it's log files. 63 | Without this setting, Hoth will write log files to the same directory 64 | Hoth is located within. This is not recomended as your will have content 65 | mixed into your Hoth code. 66 | **/ 67 | setGlobalDatabasePath(path='/logs/hoth/'); 68 | } -------------------------------------------------------------------------------- /examples/blogPost/HothConfig.cfc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Aaron Greenlee 3 | * 4 | *

Description

5 | * An example configuration object for your appication. 6 | * Customize this configuration object for your needs. 7 | * 8 | * Created 9 | * 2/9/2011 10:22:19 AM 10 | * 11 | * @author Aaron Greenlee 12 | * @version 1 13 | * @see N/A 14 | **/ 15 | 16 | component 17 | implements = 'Hoth.object.iHothConfig' 18 | extends = 'Hoth.object.CoreConfig' 19 | accessors = true 20 | { 21 | 22 | /** What is the name of your application? */ 23 | property 24 | name='applicationName' 25 | default='Amazing ColdFusion Club'; 26 | 27 | /** How many seconds should we lock file operations? 28 | For most operations this is exclusive to a unique exception. */ 29 | property 30 | name='timeToLock' 31 | default='1'; 32 | 33 | /** Where would you like Hoth to save exception data? 34 | This folder should be empty. */ 35 | property 36 | name='logPath' 37 | default='/your_mapping/hoth/cfmlClub'; 38 | 39 | // ------------------------------------------------------------------------------ 40 | /** Would you like new exceptions to be emailed to you? */ 41 | property 42 | name='EmailNewExceptions' 43 | default='true'; 44 | 45 | /** What address(es) should receive these e-mails? */ 46 | property 47 | name='EmailNewExceptionsTo' 48 | default='you@email.com;co-worker@email.com'; 49 | 50 | /** What address would you like these emails sent from? */ 51 | property 52 | name='EmailNewExceptionsFrom' 53 | default='you@email.com'; 54 | 55 | /** Would you like the raw JSON attached to the e-mail? */ 56 | property 57 | name='EmailNewExceptionsFile' 58 | default='true'; 59 | // ------------------------------------------------------------------------------ 60 | 61 | /** 62 | The mapping where you would like Hoth to write it's log files. 63 | Without this setting, Hoth will write log files to the same directory 64 | Hoth is located within. This is not recomended as your will have content 65 | mixed into your Hoth code. 66 | **/ 67 | setGlobalDatabasePath(path='/logs/hoth/'); 68 | } -------------------------------------------------------------------------------- /examples/blogPost/ImplementReportingWithColdBox.txt: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright Aaron Greenlee 3 | * 4 | *

Description

5 | * A ColdBox event handler to allow Hoth reporting. 6 | * 7 | * Created 8 | * 2/9/2011 11:27:25 AM 9 | * 10 | * @author Aaron Greenlee 11 | * @version 1 12 | * @see N/A 13 | **/ 14 | component { 15 | // Executed before any other method within this CFC 16 | public void function preHandler(required Event) 17 | { 18 | var rc = Event.getCollection(); 19 | var prc = Event.getCollection(private=true); 20 | 21 | // Only allow access for debug mode. This 22 | // ensures that you have to know the debugpassword 23 | // to access Hoth 24 | if (!getDebugMode()) 25 | { 26 | redirectToNewEvent(event='home',eventObject=Event); 27 | } 28 | 29 | // If we get this far, we have access to view Hoth. 30 | // Create a new Hoth Report instance and place it in the 31 | // prc struct. 32 | prc.HothReporter = new Hoth.HothReporter( new config.HothConfig() ); 33 | } 34 | 35 | public void function index (required Event) { 36 | var rc = Event.getCollection(); 37 | var prc = Event.getCollection(private=true); 38 | 39 | // Return Hoth's inital view 40 | Event.renderData(type='html',data=prc.HothReporter.getReportView()); 41 | 42 | return; 43 | } 44 | 45 | public void function report (required Event) { 46 | var rc = Event.getCollection(); 47 | var prc = Event.getCollection(private=true); 48 | 49 | // Return a specific report. If no exception is requested by 50 | // hash id then all of the hashes are returned. This 51 | // acts like an index so we can click on specific errors. 52 | local.report = (structKeyExists(rc, 'exception') 53 | ? rc.exception 54 | : 'all'); 55 | 56 | // Return the JSON 57 | Event.renderData(type='json',data=prc.HothReporter.report(local.report)); 58 | 59 | return; 60 | } 61 | 62 | public void function delete (required Event) { 63 | var rc = Event.getCollection(); 64 | var prc = Event.getCollection(private=true); 65 | 66 | // We can delete all exceptions at once! 67 | if (!structKeyExists(rc, 'exception')) 68 | { 69 | rc.exception = 'all'; 70 | } 71 | 72 | // Or, we can delete a specific exception using the hash id 73 | local.result = prc.HothReporter.delete(rc.exception); 74 | 75 | // Return the results as JSON. 76 | Event.renderData(type='json',data=local.result); 77 | 78 | return; 79 | } 80 | } -------------------------------------------------------------------------------- /object/CoreConfig.cfc: -------------------------------------------------------------------------------- 1 | /** 2 | Aaron Greenlee 3 | http://aarongreenlee.com/ 4 | 5 | This work is licensed under a Creative Commons Attribution-Share-Alike 3.0 6 | Unported License. 7 | 8 | // Original Info ----------------------------------------------------------- 9 | Author : Aaron Greenlee 10 | Created : 10/01/2010 11 | 12 | Core configuration object for Hoth. This object provides all the 13 | functionality for a Hoth Config Object. Individual implementations should 14 | extend this object and provide their own values within the property 15 | declaration. 16 | 17 | // ------------------------------------------------------------------------- 18 | Modified : 12/13/2010 10:04:06 AM by Aaron Greenlee. 19 | - Added support for global settings. 20 | 21 | */ 22 | component 23 | accessors='true' 24 | { 25 | 26 | /** Construct a configuration object for Hoth. */ 27 | public function init () 28 | { 29 | local.md = getMetadata(this); 30 | local.n = arrayLen(local.md.properties); 31 | for (local.i=1; local.i <= local.n; local.i++) { 32 | local.fn = this['set' & local.md.properties[local.i].name]; 33 | local.fn(local.md.properties[local.i]['default']); 34 | } 35 | return this; 36 | } 37 | 38 | public void function setGlobalDatabasePath(required string path) { 39 | variables.GlobalDatabasePath = arguments.path; 40 | } 41 | public string function getGlobalDatabasePath() { 42 | return (structKeyExists(variables, 'GlobalDatabasePath')) 43 | ? variables.GlobalDatabasePath 44 | : '/Hoth/db/'; 45 | } 46 | 47 | /** Expands a path **/ 48 | public string function getLogPathExpanded () 49 | { 50 | if (!structKeyExists(variables, 'logPathIsRelative')) { 51 | variables.logPathIsRelative = false; 52 | } 53 | return variables.logPathIsRelative ? expandPath( getLogPath() ) : getLogPath(); 54 | } 55 | 56 | /** Return a path for Hoth. */ 57 | public string function getPath (name) 58 | { 59 | switch (arguments.name) { 60 | // Sub-Directories 61 | case 'incidents' : 62 | case 'exceptions' : 63 | return getLogPathExpanded() & '/' & lcase(arguments.name); 64 | break; 65 | 66 | // Files 67 | case 'exceptionIndex' : 68 | case 'exceptionReport' : 69 | case 'exceptionReportActivity' : 70 | return getLogPathExpanded() & '/' & lcase(arguments.name) & '.log'; 71 | break; 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /examples/ColdFusion/HothReportUI.cfc: -------------------------------------------------------------------------------- 1 | // This CFC offers no protection--thus, anyone can access this. 2 | // You can implement this by renaming the CFC with a UUID--that can secure 3 | // this through obscurity. But, I prefer the approach shown in the ColdBox 4 | // example. That is what I use. I have not tried this code :( 5 | 6 | // You should replace the "new Hoth.config.HothConfig()" lines with the 7 | // classname path to your HothConfig. Hoth will generate a report for the 8 | // application's HothConfig you provide. 9 | 10 | // ----------------------------------------------------------------------- 11 | // THIS IS AN EXAMPLE AND ONLY AN EXAMPLE 12 | // ----------------------------------------------------------------------- 13 | // HOW YOU IMPLEMENT REPORTING IS REALLY YOUR BUSINESS SINCE NO ONE SHOULD 14 | // ACCESS YOUR REPORT--OR KNOW HOW TO ACCESS YOUR REPORT--BUT YOU!!!!!!!!! 15 | // 16 | // This CFC should work right out of the box for the Example HOTH data. 17 | // You will need to change the path to your config for sure. 18 | // 19 | // Feel free to add anything else you want (password/IP check?) to this file 20 | // as it should become part of your code base. 21 | 22 | component { 23 | 24 | // You will definitely want to change this path... 25 | variables.ApplicationsHothConfig = new Hoth.config.HothConfig(); 26 | 27 | /** Loads the Web UI (HTML) **/ 28 | remote function index () returnformat='plain' { 29 | local.HothReport = new Hoth.HothReporter(variables.ApplicationsHothConfig); 30 | return local.HothReport.getReportView(); 31 | } 32 | 33 | /** Access Hoth report data as JSON. 34 | @exception If not provided a list of exceptions will be returned. 35 | If provided, the value should be an exception hash which 36 | modified the behavior to return information for only 37 | that exception. **/ 38 | remote function report (string exception) returnformat='JSON' { 39 | local.report = (structKeyExists(arguments, 'exception') 40 | ? arguments.exception 41 | : 'all'); 42 | 43 | local.HothReport = new Hoth.HothReporter(variables.ApplicationsHothConfig); 44 | return local.HothReport.report(local.report); 45 | } 46 | 47 | /** Delete a report. **/ 48 | remote function delete (string exception)returnformat='JSON' { 49 | if (!structKeyExists(arguments, 'exception')) 50 | { 51 | // We can delete all exceptions at once! 52 | arguments.exception = 'all'; 53 | } 54 | 55 | local.HothReport = new Hoth.HothReporter(variables.ApplicationsHothConfig); 56 | 57 | // Delete! 58 | return local.HothReport.delete(arguments.exception); 59 | } 60 | } -------------------------------------------------------------------------------- /extras/ColdBoxInterceptor.cfc: -------------------------------------------------------------------------------- 1 | /* 2 | -------------------------------------------------------------------- 3 | I configure and load Hoth into the ColdBox cache 4 | -------------------------------------------------------------------- 5 | Define settings in ColdBox.cfc for example: 6 | interceptors = [ 7 | //Autowire 8 | { 9 | class="coldbox.system.interceptors.Autowire", 10 | properties={} 11 | }, 12 | //SES 13 | { 14 | class="coldbox.system.interceptors.SES", 15 | properties={} 16 | }, 17 | //HothTracker 18 | { 19 | class="hoth.extras.ColdBoxInterceptor", 20 | properties={ 21 | EmailNewExceptions = true, 22 | EmailNewExceptionsFile = true, 23 | EmailNewExceptionsTo = "kaboom@mysite.com", 24 | EmailNewExceptionsFrom = "server@mysite.com" 25 | } 26 | } 27 | ]; 28 | -------------------------------------------------------------------- 29 | */ 30 | component 31 | { 32 | 33 | /* CONSTRUCTOR 34 | ------------------------------------------- */ 35 | 36 | /** 37 | * This is the configuration method for the interceptor 38 | */ 39 | void function Configure() 40 | { 41 | // check for required settings 42 | if ( !propertyExists( "EmailNewExceptionsTo" ) ) 43 | { 44 | getPlugin( "logger" ).fatal( "hoth.extras.ColdBoxInterceptor.Configure", "The required 'EmailNewExceptionsTo' property has not been defined" ); 45 | throw( 46 | type="hoth.extras.ColdBoxInterceptor" 47 | , message="The required 'EmailNewExceptionsTo' property has not been defined" 48 | ); 49 | } 50 | 51 | // Use ColdBox settings if not specified 52 | if ( !propertyExists( "applicationName" ) ) 53 | { 54 | setProperty( "applicationName", getSetting( "AppName" ) & " (" & getSetting( "Environment" ) & ")" ); 55 | } 56 | if ( !propertyExists( "logPath" ) ) 57 | { 58 | setProperty( "logPath", getSetting( "ApplicationPath" ) & "logs/hoth" ); 59 | setProperty( "logPathIsRelative", false ); 60 | } 61 | 62 | // Optional settings 63 | if ( !propertyExists( "cacheKeyName" ) ) 64 | { 65 | setProperty( "cacheKeyName", "hothtracker" ); 66 | } 67 | } 68 | 69 | /* INTERCEPTION POINTS 70 | ------------------------------------------- */ 71 | 72 | void function afterAspectsLoad( required any event, required struct interceptData ) 73 | { 74 | var HothConfig = ""; 75 | var HothTracker = ""; 76 | var key = ""; 77 | var properties = getProperties(); 78 | 79 | HothConfig = new hoth.config.HothConfig(); 80 | 81 | for ( key in properties ) 82 | { 83 | // use evaluate to dynamically called setters 84 | if ( StructKeyExists( HothConfig, "set" & key ) ) 85 | { 86 | evaluate( "HothConfig.set#key#( properties[ key ] )" ); 87 | } 88 | } 89 | 90 | HothTracker = new Hoth.HothTracker( HothConfig ); 91 | 92 | // store in ColdBox Cache 93 | getColdboxOCM().set( getProperty( 'cacheKeyName' ), HothTracker, 0 ); 94 | 95 | getPlugin( "logger" ).info( "hoth.extras.ColdBoxInterceptor", "HothTracker configured and loaded in ColdBox cache using key '#getProperty( 'cacheKeyName' )#'" ); 96 | } 97 | 98 | } -------------------------------------------------------------------------------- /config/HothConfig.cfc: -------------------------------------------------------------------------------- 1 | /** 2 | Aaron Greenlee 3 | http://aarongreenlee.com/ 4 | 5 | This work is licensed under a Creative Commons Attribution-Share-Alike 3.0 6 | Unported License. 7 | 8 | // Original Info ----------------------------------------------------------- 9 | Author : Aaron Greenlee 10 | Created : 10/01/2010 11 | 12 | Default configuration for Hoth. 13 | 14 | */ 15 | component 16 | implements='Hoth.object.iHothConfig' 17 | extends='Hoth.object.CoreConfig' 18 | accessors=true { 19 | 20 | // ------------------------------------------------------------------------- 21 | // BASIC HOTH SETTINGS (required) 22 | // ------------------------------------------------------------------------- 23 | /** What is the name of your application? */ 24 | property name='applicationName' default='HothDefaultConfig'; 25 | 26 | /** How many seconds should we lock file operations? 27 | For most operations this is exclusive to a unique exception. */ 28 | property name='timeToLock' default='1'; 29 | 30 | /** Where would you like Hoth to save exception data? 31 | This folder should be empty when you start. */ 32 | property name='logPath' default='/Hoth/examples/Example_Logs'; 33 | 34 | /** Is the log file location relative to the webroot? 35 | This folder should be empty when you start. */ 36 | property name='logPathIsRelative' default='true'; 37 | 38 | // ------------------------------------------------------------------------- 39 | // HOTH EMAIL SETTINGS (required) 40 | // ------------------------------------------------------------------------- 41 | /** Would you like new exceptions to be emailed to you? */ 42 | property name='EmailNewExceptions' default='false'; 43 | 44 | /** What address(es) should receive these e-mails? */ 45 | property name='EmailNewExceptionsTo' default='you@yourdomain.com'; 46 | 47 | /** What address would you like these emails sent from? */ 48 | property name='EmailNewExceptionsFrom' default='hoth@yourdomain.com'; 49 | 50 | /** Would you like the raw JSON attached to the e-mail? */ 51 | property name='EmailNewExceptionsFile' default='false'; 52 | 53 | /** Would you like HTML emails which contain the exception? */ 54 | property name='EmailExceptionsAsHTML' default='false'; 55 | 56 | // ------------------------------------------------------------------------- 57 | // HOTH REPORT SETTINGS (required) 58 | // ------------------------------------------------------------------------- 59 | 60 | /** How you access the Hoth reports is up to you. When the reports are 61 | generated Hoth needs to know how to build links so you can navigate 62 | the report and get information from the server. 63 | 64 | You are responsible for deciding how you wish to access reports. Once 65 | you have figured that out, please, write the full URL here. 66 | **/ 67 | property 68 | name='HothReportURL' 69 | default='http://office/lib/Hoth/examples/ColdFusion/HothReportUI.cfc'; 70 | 71 | // ------------------------------------------------------------------------- 72 | // Constructor 73 | // ------------------------------------------------------------------------- 74 | public function init() 75 | { 76 | super.init(); 77 | return this; 78 | } 79 | } -------------------------------------------------------------------------------- /object/HothApplicationManager.cfc: -------------------------------------------------------------------------------- 1 | /** 2 | Aaron Greenlee 3 | http://aarongreenlee.com/ 4 | 5 | This work is licensed under a Creative Commons Attribution-Share-Alike 3.0 6 | Unported License. 7 | 8 | // Original Info ----------------------------------------------------------- 9 | Author : Aaron Greenlee 10 | Created : 12/13/2010 11 | 12 | Responsible for helping Hoth report for multiple applications. 13 | */ 14 | component 15 | name = 'HothApplicationManager' 16 | accessors = true 17 | { 18 | property name='applications' type='array'; 19 | 20 | // The filename that holds application knowledge. 21 | VARIABLES.APP_LOCK_KEY = 'HothApplicationDBFileLock'; 22 | 23 | /** Constructor. 24 | * @HothConfig Requires a HothConfig Object. 25 | */ 26 | public Hoth.object.HothApplicationManager function init( 27 | required HothConfig 28 | ){ 29 | 30 | setApplications( loadApplicationsFromDisk(HothConfig) ); 31 | 32 | return this; 33 | } 34 | 35 | /** To allow for easy reporting, Hoth needs to be able to track new 36 | applications (or really, new log paths). When a new instance of 37 | HothTracker is created, this method will be called. **/ 38 | public boolean function learnApplication( 39 | required HothConfig 40 | ){ 41 | // Prevent any other threads from saving our new application 42 | lock 43 | name=VARIABLES.APP_LOCK_KEY 44 | timeout=arguments.HothConfig.getTimeToLock() 45 | type="exclusive" 46 | { 47 | local.knownApplications = 48 | loadApplicationsFromDisk(argumentCollection=arguments); 49 | 50 | for(local.index in local.knownApplications) 51 | { 52 | // Confirm our keys exist 53 | if (structKeyExists(local.index, 'logPath')) 54 | { 55 | // If we find the same logPath, we know about this 56 | // application and need to exit. 57 | if (local.index.logPath == arguments.HothConfig.getLogPath()) 58 | { 59 | return false; 60 | } 61 | } 62 | } 63 | 64 | // We did not find out application path within the file. 65 | // Create the struct and append it to our array. 66 | local.applicationDataToSave = 67 | { 68 | 'applicationName' = arguments.HothConfig.getApplicationName() 69 | ,'logPath' = arguments.HothConfig.getLogPath() 70 | ,'created' = now() 71 | }; 72 | arrayAppend( 73 | local.knownApplications 74 | ,local.applicationDataToSave 75 | ); 76 | 77 | // Save the contents of the entire array, replacing the entire file 78 | local.path = arguments.HothConfig.getGlobalDatabasePath(); 79 | fileWrite( 80 | expandPath(arguments.HothConfig.getGlobalDatabasePath() & 'applications.hoth') 81 | ,serializeJSON(local.knownApplications) 82 | ,'UTF-8' 83 | ); 84 | } 85 | 86 | return true; 87 | } 88 | 89 | /** Loads applications already observed by Hoth from disk. 90 | * This process should be locked by the calling method. 91 | * @HothConfig Requires a HothConfig Object. */ 92 | private array function loadApplicationsFromDisk ( 93 | required HothConfig 94 | ){ 95 | local.path = arguments.HothConfig.getGlobalDatabasePath(); 96 | local.appfile = expandPath(arguments.HothConfig.getGlobalDatabasePath() & 'applications.hoth'); 97 | 98 | // Return an empty array if the appFile does not exist. 99 | if (!fileExists( local.appfile ) ) 100 | { 101 | return []; 102 | } 103 | 104 | local.applicationsFound = fileRead( local.appfile ); 105 | 106 | // Delete the database if the file is invalid. 107 | if (!isJSON(local.applicationsFound)) 108 | { 109 | fileDelete( local.appfile ); 110 | return []; 111 | } 112 | 113 | // Convert the file to our desired structure 114 | local.parsedDB = deserializeJSON(local.applicationsFound); 115 | 116 | return local.parsedDB; 117 | } 118 | } -------------------------------------------------------------------------------- /test/unit/HothApplicationManagerTest.cfc: -------------------------------------------------------------------------------- 1 | /** 2 | Aaron Greenlee 3 | http://aarongreenlee.com/ 4 | 5 | This work is licensed under a Creative Commons Attribution-Share-Alike 3.0 6 | Unported License. 7 | 8 | // Original Info ----------------------------------------------------------- 9 | Author : Aaron Greenlee 10 | Created : 12/13/2010 10:17:31 AM 11 | 12 | Unit Test for HothApplicationManager 13 | 14 | // Modifications :--------------------------------------------------------- 15 | 16 | */ 17 | 18 | /** Unit test for Hoth.HothTracker */ 19 | component extends="mxunit.framework.TestCase" 20 | { 21 | 22 | variables.testDB = '/Hoth/test/db/'; 23 | variables.appFile = expandPath(variables.testDB & 'applications.hoth'); 24 | 25 | /** Constructor */ 26 | public void function setUp() 27 | { 28 | // Load our test config 29 | HothConfig = new Hoth.test.HothConfig(); 30 | HothConfig.setGlobalDatabasePath(variables.testDB); 31 | 32 | // Change the global settings for the test 33 | HothConfig.GlobalHothSettings.globalDatabase = variables.testDB; 34 | 35 | // Create our SUT 36 | HothApplicationManager = 37 | new Hoth.object.HothApplicationManager(HothConfig); 38 | 39 | // Write our test application data 40 | local.applicationToSave = 41 | [{ 42 | 'applicationName' = 'HothUnitTestFake' 43 | ,'logPath' = '/Hoth/test/logs_not_real' 44 | ,'created' = 0 45 | }]; 46 | fileWrite( 47 | variables.appFile 48 | ,serializeJSON(local.applicationToSave) 49 | ,'UTF-8' 50 | ); 51 | 52 | return; 53 | } 54 | 55 | /** Ensure our test db directory exists. **/ 56 | public void function beforeTests () 57 | { 58 | if (!directoryExists(variables.testDB)) 59 | directoryCreate(variables.testDB); 60 | 61 | return; 62 | } 63 | 64 | /** Delete our test db file. **/ 65 | public void function afterTests () 66 | { 67 | // Delete test db unless a test triggered the delete 68 | if (fileExists(variables.appFile)) 69 | { 70 | fileDelete(variables.appFile); 71 | } 72 | } 73 | 74 | // ------------------------------------------------------------------------- 75 | /** Ensure we can read our application database file. **/ 76 | public void function loadApplicationsFromDisk() 77 | { 78 | makePublic(HothApplicationManager, 'loadApplicationsFromDisk'); 79 | 80 | // Confirm we have our application created in beforeTests(); 81 | local.appsFound = arrayLen( 82 | HothApplicationManager.loadApplicationsFromDisk(HothConfig) 83 | ); 84 | 85 | assertEquals( 86 | 1 87 | ,local.appsFound 88 | ,'Invalid application db.' 89 | ); 90 | 91 | return; 92 | } 93 | 94 | /** Ensure we delete an invalid application database file. **/ 95 | public void function loadApplicationsFromDisk_Deletes_Invalid_JSON() 96 | { 97 | makePublic(HothApplicationManager, 'loadApplicationsFromDisk'); 98 | 99 | // Save invalid data and expect the file to be deleted 100 | fileWrite( 101 | variables.appFile 102 | ,'I am not JSON' 103 | ,'UTF-8' 104 | ); 105 | 106 | // Now, we expect zero. 107 | local.appsFound = arrayLen( 108 | HothApplicationManager.loadApplicationsFromDisk(HothConfig) 109 | ); 110 | 111 | assertEquals( 112 | 0 113 | ,local.appsFound 114 | ,'Should have deleted the file and returned zero.' 115 | ); 116 | 117 | assert( 118 | fileExists(variables.testDB & variables.appFile) == false 119 | ,'Should have deleted the file and returned zero.' 120 | ); 121 | 122 | return; 123 | } 124 | 125 | /** Ensure we can learn about our applications. **/ 126 | public void function learnApplication() 127 | { 128 | 129 | local.newApplication = 130 | HothApplicationManager.learnApplication(HothConfig); 131 | 132 | assert(local.newApplication, 'We should have a new application.'); 133 | 134 | // Performing the same test twice should now return false since we 135 | // already know about this application. 136 | 137 | local.newApplication = 138 | HothApplicationManager.learnApplication(HothConfig); 139 | 140 | assertFalse(local.newApplication, 'We should NOT have a new application.'); 141 | 142 | return; 143 | } 144 | } -------------------------------------------------------------------------------- /test/unit/HothTrackerTest.cfc: -------------------------------------------------------------------------------- 1 | /** 2 | Aaron Greenlee 3 | http://aarongreenlee.com/ 4 | 5 | This work is licensed under a Creative Commons Attribution-Share-Alike 3.0 6 | Unported License. 7 | 8 | // Original Info ----------------------------------------------------------- 9 | Author : Aaron Greenlee 10 | Created : 10/01/2010 11 | 12 | Unit Test for HothTracker 13 | 14 | // Modifications :--------------------------------------------------------- 15 | Modified : 12/13/2010 9:52:41 AM by Aaron Greenlee. 16 | - Now supporting ColdBox 3.0 RC1 17 | */ 18 | 19 | import coldbox.system.testing.*; 20 | 21 | /** Unit test for Hoth.HothTracker */ 22 | component extends="mxunit.framework.TestCase" { 23 | 24 | /** Constructor */ 25 | public void function setUp() { 26 | MockBox = new MockBox(); 27 | 28 | // Load our test config 29 | HothConfig = new Hoth.test.HothConfig(); 30 | 31 | variables.paths = 32 | { 33 | exceptions = HothConfig.getPath('exceptions') 34 | ,incidents = HothConfig.getPath('incidents') 35 | }; 36 | 37 | // SUT 38 | variables.HothTracker = MockBox 39 | .createMock(classname='Hoth.HothTracker',callLogging=true) 40 | .init(HothConfig); 41 | 42 | // Delete all previous logs 43 | local.files = directoryList(variables.paths.exceptions,false,'path','*','size desc'); 44 | if (!arrayIsEmpty(local.files)) 45 | for (local.f in local.files) 46 | fileDelete(local.f); 47 | 48 | // Delete all previous logs 49 | local.files = directoryList(variables.paths.incidents,false,'path','*','size desc'); 50 | if (!arrayIsEmpty(local.files)) 51 | for (local.f in local.files) 52 | fileDelete(local.f); 53 | 54 | return; 55 | } 56 | 57 | // ------------------------------------------------------------------------------ 58 | /** Test default ColdFusion exception tracking. */ 59 | public void function track() { 60 | try { 61 | coldfusion = undefinedVariable; 62 | } catch (any exception) { 63 | local.hashOfStack = hash(lcase(exception.stacktrace),'SHA'); 64 | local.HothOk = variables.HothTracker.track(exception); 65 | 66 | } 67 | 68 | local.file = local.hashOfStack & '.log'; 69 | // Verify an exception was saved. 70 | assert( fileExists(variables.paths.exceptions & '/' & local.file), 'Expected #local.hashOfStack#.log exception file.'); 71 | assert( fileExists(variables.paths.incidents & '/' & local.file), 'Expected #local.hashOfStack#.log incident file.'); 72 | 73 | return; 74 | } 75 | /** Test a ColdBox exception. */ 76 | public void function trackForColdBox() { 77 | try { 78 | coldbox = undefinedVariable; 79 | } catch (any exception) { 80 | local.ExceptionBean = new coldbox.system.web.context.ExceptionBean(errorStruct=exception); 81 | local.hashOfStack = hash(lcase(exception.stacktrace),'SHA'); 82 | local.HothOk = variables.HothTracker.track(exception); 83 | } 84 | local.file = local.hashOfStack & '.log'; 85 | // Verify an exception was saved. 86 | assert( fileExists(variables.paths.exceptions & '/' & local.file), 'Expected #local.hashOfStack#.log exception file.'); 87 | assert( fileExists(variables.paths.incidents & '/' & local.file), 'Expected #local.hashOfStack#.log incident file.'); 88 | 89 | return; 90 | } 91 | 92 | public void function trackDuplicates() { 93 | local.loops = 5; 94 | 95 | // Hit the same exception X times. 96 | for (local.i=1; local.i <= local.loops; local.i++) { 97 | try { 98 | apples = undefinedVariable2; 99 | } catch (any exception) { 100 | local.hashOfStack = hash(lcase(exception.stacktrace),'SHA'); 101 | variables.HothTracker.track(exception); 102 | } 103 | } 104 | local.file = local.hashOfStack & '.log'; 105 | // Verify an exception was saved. 106 | assert( fileExists(variables.paths.exceptions & '/' & local.file), 'Expected #local.hashOfStack#.log exception file.'); 107 | 108 | // Verify our incident file was saved 109 | local.incidentFile = variables.paths.incidents & '/' & local.file; 110 | assert( fileExists(local.incidentFile), 'Expected #local.file# incident file.'); 111 | 112 | // Verify our incident file has five incidents (one per line) 113 | local.incidents = FileOpen(local.incidentFile, 'read'); 114 | local.lines = 0; 115 | while( !FileisEOF(local.incidents) ) { 116 | ++local.lines; 117 | local.line = FileReadLine(local.incidents); 118 | assert( isDate(local.line) , 'Expected date; Received "#local.line#"'); 119 | } 120 | FileClose(local.incidents); 121 | 122 | assert(local.lines == local.loops, 'Expected #local.loops# lines. #local.lines# found'); 123 | 124 | return; 125 | } 126 | } -------------------------------------------------------------------------------- /HothReporter.cfc: -------------------------------------------------------------------------------- 1 | /** 2 | Aaron Greenlee 3 | http://aarongreenlee.com/ 4 | 5 | This work is licensed under a Creative Commons Attribution-Share-Alike 3.0 6 | Unported License. 7 | 8 | // Original Info ----------------------------------------------------------- 9 | Author : Aaron Greenlee 10 | Created : 01/12/2011 11 | 12 | HothReporter offers a simple Web UI to report the errors observed by Hoth. 13 | 14 | // Modifications :--------------------------------------------------------- 15 | 16 | */ 17 | component 18 | name='HothReporter' 19 | accessors=false 20 | output="false" 21 | { 22 | public Hoth.HothReporter function init (HothConfig) 23 | { 24 | // If a config object was not provided we 25 | // will use our default. 26 | variables.Config = (structKeyExists(arguments, 'HothConfig')) 27 | ? arguments.HothConfig 28 | : new Hoth.config.HothConfig(); 29 | 30 | VARIABLES._NAME = 'Hoth_' & variables.Config.getApplicationName(); 31 | 32 | variables.exceptionKeys = ['detail','type','tagcontext','stacktrace','message'];// Required exception keys 33 | variables.logPathIsRelative = variables.Config.getLogPathIsRelative(); 34 | variables.paths.LogPath = variables.Config.getLogPathExpanded(); // Get the root location for our logging. 35 | variables.paths.Exceptions = variables.Config.getPath('exceptions'); // Track the unique exceptions. 36 | variables.paths.Incidents = variables.Config.getPath('incidents'); // Track the hits per exception. 37 | variables.paths.Report = variables.Config.getPath('exceptionReport'); // The actual report 38 | variables.paths.Activity = variables.Config.getPath('exceptionReportActivity'); // Track when we save things. Helps understand volume. 39 | //variables.paths.Index = variables.Config.getPath('exceptionIndex'); // Tracks the exception keys to prevent duplication 40 | 41 | return this; 42 | } 43 | 44 | /** Quick report. Really a work in process. 45 | * @exception Accepts a hash value or 'all' 46 | **/ 47 | public struct function report (required string exception) 48 | { 49 | if (arguments.exception=='all') 50 | { 51 | return generateExceptionIndex(); 52 | } else { 53 | local.filepath = variables.paths.Exceptions & '/' & arguments.exception; 54 | 55 | local.exception = (fileExists(local.filepath)) 56 | ? fileRead(local.filepath) 57 | : serializeJSON ({'message'="That report no longer exists."}); 58 | 59 | return deserializeJSON (local.exception); 60 | } 61 | } 62 | 63 | /** Quick report. Really a work in process. 64 | * @exception Accepts a hash value or 'all' 65 | **/ 66 | public array function delete (required string exception) 67 | { 68 | 69 | local.response = []; 70 | if (arguments.exception == 'all') 71 | { 72 | lock name=VARIABLES._NAME timeout=variables.Config.getTimeToLock() type="exclusive" { 73 | directoryDelete(variables.paths.Exceptions, true); 74 | directoryDelete(variables.paths.Incidents, true); 75 | directoryCreate(variables.paths.Exceptions); 76 | directoryCreate(variables.paths.Incidents); 77 | } 78 | } else { local.exceptionPath = variables.paths.Exceptions & '/' & arguments.exception; 79 | local.incidentPath = variables.paths.Incidents & '/' & arguments.exception; 80 | 81 | local.response = []; 82 | 83 | if (fileExists(local.exceptionPath)) 84 | { 85 | fileDelete(local.exceptionPath); 86 | arrayAppend(local.response, "Exception file deleted."); 87 | } else { 88 | arrayAppend(local.response, "Exception file did not exist!"); 89 | } 90 | if (fileExists(local.incidentPath)) 91 | { 92 | fileDelete(local.incidentPath); 93 | arrayAppend(local.response, "Incident record file deleted."); 94 | } else { 95 | arrayAppend(local.response, "Incident record file not exist!"); 96 | } 97 | return local.response; 98 | } 99 | } 100 | 101 | /** Return the report's view **/ 102 | public string function getReportView () { 103 | local.view = fileRead(expandPath('/Hoth') & '/views/report.html'); 104 | 105 | // Replace the Hoth URL 106 | return replaceNoCase( 107 | local.view 108 | ,'${HOTH_REPORT_URL}' 109 | ,variables.Config.getHothReportURL()); 110 | } 111 | 112 | // ------------------------------------------------------------------------- 113 | private struct function generateExceptionIndex() { 114 | // Read our file system 115 | local.exceptions = directoryList (variables.paths.Exceptions,false); 116 | local.incidents = directoryList (variables.paths.Exceptions,false); 117 | 118 | local.report = {}; 119 | for (i=1;i LTE ArrayLen(local.exceptions);i=i+1) { 120 | 121 | local.instance = {}; 122 | local.instance.filename = 123 | listLast(local.exceptions[i],'\/'); 124 | 125 | if (left(local.instance.filename, 1) != '_') 126 | { 127 | //local.instance.exceptionDetail = 128 | //fileRead (local.exceptions[i]); 129 | 130 | if (!fileExists(variables.paths.Incidents & '/' & local.instance.filename)) 131 | { 132 | local.instances = ''; 133 | } else { 134 | local.instances = 135 | fileRead(variables.paths.Incidents & '/' & local.instance.filename); 136 | } 137 | 138 | local.instance.incidentcount = listLen(local.instances,chr(10)); 139 | 140 | // Save our report 141 | local.report[local.instance.filename] = local.instance; 142 | } 143 | } 144 | 145 | return local.report; 146 | } 147 | } -------------------------------------------------------------------------------- /examples/Example_Logs/exceptions/049000E8B1A24DA94AD81BB289977551ECFA16FC.log: -------------------------------------------------------------------------------- 1 | {"MESSAGE":"Event handler exception.","FORMAT":[{"RAW_TRACE":"\tat cfBugReport2ecfm1516481789.runPage(C:\\inetpub\\lib\\coldbox-platform\\system\\includes\\BugReport.cfm:15)","ID":"CFOUTPUT","TEMPLATE":"C:\\inetpub\\lib\\coldbox-platform\\system\\includes\\BugReport.cfm","LINE":15,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfExceptionService2ecfc724947867$funcRENDERBUGREPORT.runFunction(C:\\inetpub\\lib\\coldbox-platform\\system\\web\\services\\ExceptionService.cfc:90)","ID":"CFINCLUDE","TEMPLATE":"C:\\inetpub\\lib\\coldbox-platform\\system\\web\\services\\ExceptionService.cfc","LINE":90,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfColdbox2ecfc1895015153$funcPROCESSCOLDBOXREQUEST.runFunction(C:\\inetpub\\lib\\coldbox-platform\\system\\Coldbox.cfc:319)","ID":"CF_TEMPLATEPROXY","TEMPLATE":"C:\\inetpub\\lib\\coldbox-platform\\system\\Coldbox.cfc","LINE":319,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfApplication2ecfc990484639$funcONREQUESTSTART.runFunction(C:\\inetpub\\foobar\\Application.cfc:113)","ID":"CF_UDFMETHOD","TEMPLATE":"C:\\inetpub\\foobar\\Application.cfc","LINE":113,"TYPE":"CFML","COLUMN":0}],"STACK":"coldfusion.runtime.EventHandlerException: Event handler exception.\r\n\tat coldfusion.runtime.AppEventInvoker.onRequestStart(AppEventInvoker.java:266)\r\n\tat coldfusion.filter.ApplicationFilter.invoke(ApplicationFilter.java:349)\r\n\tat coldfusion.filter.RequestMonitorFilter.invoke(RequestMonitorFilter.java:48)\r\n\tat coldfusion.filter.MonitoringFilter.invoke(MonitoringFilter.java:40)\r\n\tat coldfusion.filter.PathFilter.invoke(PathFilter.java:94)\r\n\tat coldfusion.filter.ExceptionFilter.invoke(ExceptionFilter.java:70)\r\n\tat coldfusion.filter.ClientScopePersistenceFilter.invoke(ClientScopePersistenceFilter.java:28)\r\n\tat coldfusion.filter.BrowserFilter.invoke(BrowserFilter.java:38)\r\n\tat coldfusion.filter.NoCacheFilter.invoke(NoCacheFilter.java:46)\r\n\tat coldfusion.filter.GlobalsFilter.invoke(GlobalsFilter.java:38)\r\n\tat coldfusion.filter.DatasourceFilter.invoke(DatasourceFilter.java:22)\r\n\tat coldfusion.filter.CachingFilter.invoke(CachingFilter.java:62)\r\n\tat coldfusion.CfmServlet.service(CfmServlet.java:200)\r\n\tat coldfusion.bootstrap.BootstrapServlet.service(BootstrapServlet.java:89)\r\n\tat jrun.servlet.FilterChain.doFilter(FilterChain.java:86)\r\n\tat com.intergral.fusionreactor.filter.FusionReactorFilter.i(FusionReactorFilter.java:566)\r\n\tat com.intergral.fusionreactor.filter.FusionReactorFilter.c(FusionReactorFilter.java:258)\r\n\tat com.intergral.fusionreactor.filter.FusionReactorFilter.doFilter(FusionReactorFilter.java:164)\r\n\tat jrun.servlet.FilterChain.doFilter(FilterChain.java:94)\r\n\tat coldfusion.monitor.event.MonitoringServletFilter.doFilter(MonitoringServletFilter.java:42)\r\n\tat coldfusion.bootstrap.BootstrapFilter.doFilter(BootstrapFilter.java:46)\r\n\tat jrun.servlet.FilterChain.doFilter(FilterChain.java:94)\r\n\tat jrun.servlet.FilterChain.service(FilterChain.java:101)\r\n\tat jrun.servlet.ServletInvoker.invoke(ServletInvoker.java:106)\r\n\tat jrun.servlet.JRunInvokerChain.invokeNext(JRunInvokerChain.java:42)\r\n\tat jrun.servlet.JRunRequestDispatcher.invoke(JRunRequestDispatcher.java:286)\r\n\tat jrun.servlet.ServletEngineService.dispatch(ServletEngineService.java:543)\r\n\tat jrun.servlet.jrpp.JRunProxyService.invokeRunnable(JRunProxyService.java:203)\r\n\tat jrunx.scheduler.ThreadPool$ThreadThrottle.invokeRunnable(ThreadPool.java:428)\r\n\tat jrunx.scheduler.WorkerThread.run(WorkerThread.java:66)\r\nCaused by: coldfusion.runtime.RequestTimedOutException: The request has exceeded the allowable time limit Tag: cfoutput\r\n\tat coldfusion.tagext.io.OutputTag.doStartTag(OutputTag.java:149)\r\n\tat cfBugReport2ecfm1516481789.runPage(C:\\inetpub\\lib\\coldbox-platform\\system\\includes\\BugReport.cfm:15)\r\n\tat coldfusion.runtime.CfJspPage.invoke(CfJspPage.java:231)\r\n\tat coldfusion.tagext.lang.IncludeTag.doStartTag(IncludeTag.java:416)\r\n\tat coldfusion.runtime.CfJspPage._emptyTcfTag(CfJspPage.java:2722)\r\n\tat cfExceptionService2ecfc724947867$funcRENDERBUGREPORT.runFunction(C:\\inetpub\\lib\\coldbox-platform\\system\\web\\services\\ExceptionService.cfc:90)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:472)\r\n\tat coldfusion.filter.SilentFilter.invoke(SilentFilter.java:47)\r\n\tat coldfusion.runtime.UDFMethod$ReturnTypeFilter.invoke(UDFMethod.java:405)\r\n\tat coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:368)\r\n\tat coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:55)\r\n\tat coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:321)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:220)\r\n\tat coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:491)\r\n\tat coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:337)\r\n\tat coldfusion.runtime.CfJspPage._invoke(CfJspPage.java:2360)\r\n\tat cfColdbox2ecfc1895015153$funcPROCESSCOLDBOXREQUEST.runFunction(C:\\inetpub\\lib\\coldbox-platform\\system\\Coldbox.cfc:319)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:472)\r\n\tat coldfusion.runtime.UDFMethod$ReturnTypeFilter.invoke(UDFMethod.java:405)\r\n\tat coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:368)\r\n\tat coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:55)\r\n\tat coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:321)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:220)\r\n\tat coldfusion.runtime.CfJspPage._invokeUDF(CfJspPage.java:2582)\r\n\tat cfApplication2ecfc990484639$funcONREQUESTSTART.runFunction(C:\\inetpub\\foobar\\Application.cfc:113)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:472)\r\n\tat coldfusion.runtime.UDFMethod$ReturnTypeFilter.invoke(UDFMethod.java:405)\r\n\tat coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:368)\r\n\tat coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:55)\r\n\tat coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:321)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:220)\r\n\tat coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:491)\r\n\tat coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:337)\r\n\tat coldfusion.runtime.AppEventInvoker.invoke(AppEventInvoker.java:88)\r\n\tat coldfusion.runtime.AppEventInvoker.onRequestStart(AppEventInvoker.java:258)\r\n\t... 29 more\r\n","DETAIL":"An exception occurred while invoking an event handler method from Application.cfc. The method name is: onRequestStart.","URL":"your.web.site.com\/404","CONTEXT":[{"RAW_TRACE":"\tat cfBugReport2ecfm1516481789.runPage(C:\\inetpub\\lib\\coldbox-platform\\system\\includes\\BugReport.cfm:15)","ID":"CFOUTPUT","TEMPLATE":"C:\\inetpub\\lib\\coldbox-platform\\system\\includes\\BugReport.cfm","LINE":15,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfExceptionService2ecfc724947867$funcRENDERBUGREPORT.runFunction(C:\\inetpub\\lib\\coldbox-platform\\system\\web\\services\\ExceptionService.cfc:90)","ID":"CFINCLUDE","TEMPLATE":"C:\\inetpub\\lib\\coldbox-platform\\system\\web\\services\\ExceptionService.cfc","LINE":90,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfColdbox2ecfc1895015153$funcPROCESSCOLDBOXREQUEST.runFunction(C:\\inetpub\\lib\\coldbox-platform\\system\\Coldbox.cfc:319)","ID":"CF_TEMPLATEPROXY","TEMPLATE":"C:\\inetpub\\lib\\coldbox-platform\\system\\Coldbox.cfc","LINE":319,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfApplication2ecfc990484639$funcONREQUESTSTART.runFunction(C:\\inetpub\\foobar\\Application.cfc:113)","ID":"CF_UDFMETHOD","TEMPLATE":"C:\\inetpub\\foobar\\Application.cfc","LINE":113,"TYPE":"CFML","COLUMN":0}]} -------------------------------------------------------------------------------- /examples/Example_Logs/exceptions/00422207A2688146A6D66DDAA034AC2B8D9F2DEA.log: -------------------------------------------------------------------------------- 1 | {"MESSAGE":"Error Messages can be seen here!","CLIENT":"Mozilla\/5.0(GreenleeBot)","FORMAT":[{"RAW_TRACE":"\tat cfCFCApplicationLoader2ecfc170290569$funcLOADCONFIGURATION.runFunction(C:\\web\\lib\\coldbox_fork\\system\\web\\loader\\CFCApplicationLoader.cfc:74)","ID":"CF_CFPAGE","TEMPLATE":"C:\\web\\lib\\coldbox_fork\\system\\web\\loader\\CFCApplicationLoader.cfc","LINE":74,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfLoaderService2ecfc484928675$funcLOADAPPLICATION.runFunction(C:\\web\\lib\\coldbox_fork\\system\\web\\services\\LoaderService.cfc:52)","ID":"CF_TEMPLATEPROXY","TEMPLATE":"C:\\web\\lib\\coldbox_fork\\system\\web\\services\\LoaderService.cfc","LINE":52,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfColdbox2ecfc1656576836$funcLOADCOLDBOX.runFunction(C:\\web\\lib\\coldbox_fork\\system\\Coldbox.cfc:71)","ID":"CF_TEMPLATEPROXY","TEMPLATE":"C:\\web\\lib\\coldbox_fork\\system\\Coldbox.cfc","LINE":71,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfApplication2ecfc749399233$funcONAPPLICATIONSTART.runFunction(C:\\inetpub\\foobar\\Application.cfc:47)","ID":"CF_UDFMETHOD","TEMPLATE":"C:\\inetpub\\foobar\\Application.cfc","LINE":47,"TYPE":"CFML","COLUMN":0}],"STACK":"coldfusion.runtime.EventHandlerException: Event handler exception.\r\n\tat coldfusion.runtime.AppEventInvoker.onApplicationStart(AppEventInvoker.java:219)\r\n\tat coldfusion.filter.ApplicationFilter.invoke(ApplicationFilter.java:242)\r\n\tat coldfusion.filter.RequestMonitorFilter.invoke(RequestMonitorFilter.java:48)\r\n\tat coldfusion.filter.MonitoringFilter.invoke(MonitoringFilter.java:40)\r\n\tat coldfusion.filter.PathFilter.invoke(PathFilter.java:94)\r\n\tat coldfusion.filter.LicenseFilter.invoke(LicenseFilter.java:27)\r\n\tat coldfusion.filter.ExceptionFilter.invoke(ExceptionFilter.java:70)\r\n\tat coldfusion.filter.ClientScopePersistenceFilter.invoke(ClientScopePersistenceFilter.java:28)\r\n\tat coldfusion.filter.GlobalsFilter.invoke(GlobalsFilter.java:38)\r\n\tat coldfusion.filter.DatasourceFilter.invoke(DatasourceFilter.java:22)\r\n\tat coldfusion.xml.rpc.CFCServlet.invoke(CFCServlet.java:138)\r\n\tat coldfusion.xml.rpc.CFCServlet.doPost(CFCServlet.java:289)\r\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:760)\r\n\tat org.apache.axis.transport.http.AxisServletBase.service(AxisServletBase.java:327)\r\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:853)\r\n\tat coldfusion.bootstrap.BootstrapServlet.service(BootstrapServlet.java:89)\r\n\tat jrun.servlet.FilterChain.doFilter(FilterChain.java:86)\r\n\tat com.intergral.fusionreactor.filter.FusionReactorFilter.b(FusionReactorFilter.java:376)\r\n\tat com.intergral.fusionreactor.filter.FusionReactorFilter.c(FusionReactorFilter.java:254)\r\n\tat com.intergral.fusionreactor.filter.FusionReactorFilter.doFilter(FusionReactorFilter.java:164)\r\n\tat jrun.servlet.FilterChain.doFilter(FilterChain.java:94)\r\n\tat coldfusion.monitor.event.MonitoringServletFilter.doFilter(MonitoringServletFilter.java:42)\r\n\tat coldfusion.bootstrap.BootstrapFilter.doFilter(BootstrapFilter.java:46)\r\n\tat jrun.servlet.FilterChain.doFilter(FilterChain.java:94)\r\n\tat jrun.servlet.FilterChain.service(FilterChain.java:101)\r\n\tat jrun.servlet.ServletInvoker.invoke(ServletInvoker.java:106)\r\n\tat jrun.servlet.JRunInvokerChain.invokeNext(JRunInvokerChain.java:42)\r\n\tat jrun.servlet.JRunRequestDispatcher.invoke(JRunRequestDispatcher.java:286)\r\n\tat jrun.servlet.ServletEngineService.dispatch(ServletEngineService.java:543)\r\n\tat jrun.servlet.jrpp.JRunProxyService.invokeRunnable(JRunProxyService.java:203)\r\n\tat jrunx.scheduler.ThreadPool$DownstreamMetrics.invokeRunnable(ThreadPool.java:320)\r\n\tat jrunx.scheduler.ThreadPool$ThreadThrottle.invokeRunnable(ThreadPool.java:428)\r\n\tat jrunx.scheduler.ThreadPool$UpstreamMetrics.invokeRunnable(ThreadPool.java:266)\r\n\tat jrunx.scheduler.WorkerThread.run(WorkerThread.java:66)\r\nCaused by: coldfusion.runtime.CfJspPage$NoSuchTemplateException: Could not find the ColdFusion component or interface lib.Hoth.facade.config\/Coldbox.\r\n\tat coldfusion.runtime.TemplateProxyFactory.getResolvedFile(TemplateProxyFactory.java:1311)\r\n\tat coldfusion.runtime.TemplateProxyFactory.getTemplateFileHelper(TemplateProxyFactory.java:1526)\r\n\tat coldfusion.cfc.ComponentProxyFactory.getProxy(ComponentProxyFactory.java:51)\r\n\tat coldfusion.runtime.CFPage.CreateObject(CFPage.java:4827)\r\n\tat coldfusion.runtime.CFPage.CreateObject(CFPage.java:4841)\r\n\tat cfCFCApplicationLoader2ecfc170290569$funcLOADCONFIGURATION.runFunction(C:\\web\\lib\\coldbox_fork\\system\\web\\loader\\CFCApplicationLoader.cfc:74)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:472)\r\n\tat coldfusion.filter.SilentFilter.invoke(SilentFilter.java:47)\r\n\tat coldfusion.runtime.UDFMethod$ReturnTypeFilter.invoke(UDFMethod.java:405)\r\n\tat coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:368)\r\n\tat coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:55)\r\n\tat coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:321)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:220)\r\n\tat coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:491)\r\n\tat coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:337)\r\n\tat coldfusion.runtime.CfJspPage._invoke(CfJspPage.java:2360)\r\n\tat cfLoaderService2ecfc484928675$funcLOADAPPLICATION.runFunction(C:\\web\\lib\\coldbox_fork\\system\\web\\services\\LoaderService.cfc:52)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:472)\r\n\tat coldfusion.filter.SilentFilter.invoke(SilentFilter.java:47)\r\n\tat coldfusion.runtime.UDFMethod$ReturnTypeFilter.invoke(UDFMethod.java:405)\r\n\tat coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:368)\r\n\tat coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:55)\r\n\tat coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:321)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:220)\r\n\tat coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:491)\r\n\tat coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:337)\r\n\tat coldfusion.runtime.CfJspPage._invoke(CfJspPage.java:2360)\r\n\tat cfColdbox2ecfc1656576836$funcLOADCOLDBOX.runFunction(C:\\web\\lib\\coldbox_fork\\system\\Coldbox.cfc:71)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:472)\r\n\tat coldfusion.filter.SilentFilter.invoke(SilentFilter.java:47)\r\n\tat coldfusion.runtime.UDFMethod$ReturnTypeFilter.invoke(UDFMethod.java:405)\r\n\tat coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:368)\r\n\tat coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:55)\r\n\tat coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:321)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:220)\r\n\tat coldfusion.runtime.CfJspPage._invokeUDF(CfJspPage.java:2582)\r\n\tat cfApplication2ecfc749399233$funcONAPPLICATIONSTART.runFunction(C:\\inetpub\\foobar\\Application.cfc:47)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:472)\r\n\tat coldfusion.filter.SilentFilter.invoke(SilentFilter.java:47)\r\n\tat coldfusion.runtime.UDFMethod$ReturnTypeFilter.invoke(UDFMethod.java:405)\r\n\tat coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:368)\r\n\tat coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:55)\r\n\tat coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:321)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:220)\r\n\tat coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:491)\r\n\tat coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:337)\r\n\tat coldfusion.runtime.AppEventInvoker.invoke(AppEventInvoker.java:88)\r\n\tat coldfusion.runtime.AppEventInvoker.onApplicationStart(AppEventInvoker.java:211)\r\n\t... 33 more\r\n","DETAIL":"Any reported details can be seen in this spot.","URL":"your\/website\/address\/printed\/Here.cfc","CONTEXT":[{"RAW_TRACE":"\tat cfCFCApplicationLoader2ecfc170290569$funcLOADCONFIGURATION.runFunction(C:\\web\\lib\\coldbox_fork\\system\\web\\loader\\CFCApplicationLoader.cfc:74)","ID":"CF_CFPAGE","TEMPLATE":"C:\\web\\lib\\coldbox_fork\\system\\web\\loader\\CFCApplicationLoader.cfc","LINE":74,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfLoaderService2ecfc484928675$funcLOADAPPLICATION.runFunction(C:\\web\\lib\\coldbox_fork\\system\\web\\services\\LoaderService.cfc:52)","ID":"CF_TEMPLATEPROXY","TEMPLATE":"C:\\web\\lib\\coldbox_fork\\system\\web\\services\\LoaderService.cfc","LINE":52,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfColdbox2ecfc1656576836$funcLOADCOLDBOX.runFunction(C:\\web\\lib\\coldbox_fork\\system\\Coldbox.cfc:71)","ID":"CF_TEMPLATEPROXY","TEMPLATE":"C:\\web\\lib\\coldbox_fork\\system\\Coldbox.cfc","LINE":71,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfApplication2ecfc749399233$funcONAPPLICATIONSTART.runFunction(C:\\inetpub\\foobar\\Application.cfc:47)","ID":"CF_UDFMETHOD","TEMPLATE":"C:\\inetpub\\foobar\\Application.cfc","LINE":47,"TYPE":"CFML","COLUMN":0}]} -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | Status as of July 2016: Hoth is stable and can help you identify, track, and prioritize your ColdFusion bugs. However, I will not be investing resources in this package going forward. I had done quite a bit of ColdFusion work as a contractor working on projects for Adobe but that time is passed. If you would like to continue to grow this project please reach out to me as I would be happy to add you as a organizer. 2 | 3 | --------------------------------------------- 4 | --------------------------------------------- 5 | --------------------------------------------- 6 | 7 | __ __ ______ .___________. __ __ 8 | | | | | / __ \ | || | | | 9 | | |__| | | | | | `---| |----`| |__| | 10 | | __ | | | | | | | | __ | 11 | | | | | | `--' | | | | | | | 12 | |__| |__| \______/ |__| |__| |__| 13 | 14 | --------------------------------------------- 15 | --------------------------------------------- 16 | --------------------------------------------- 17 | 18 | MMI?????????????????????????????????????IIIIIIIIIIIIIIIIIIIII7777777777777777MMM 19 | MM??????????????????????????????????????IIIIIIIIIIIIIIIIIIIII7777777777777777MMM 20 | MM???????????????????????????????????????IIIIIIIIIIIIIIIIIII77777777777777777MMM 21 | MM??????????????????????????????????????IIIIIIIIIIIIIIIIIIII77777777777777777MMM 22 | MM??????????????????????????????????????IIIIIIIIIIIIIIIIIIII77777777777777777MMM 23 | MM?????????????????????????????????????IIIIIIIIIIIIIIIIIII7777777777777777777MMM 24 | MM????????????????????????????????????IIIIIIIIIIIIIIIIIII77777777777777777777MMM 25 | MM??????????????????????????????????IIIIIIIIIIIIIIIIIIII7777777777777777777$$MMM 26 | MM?????????????????????????????????IIIIIIIIIIIIIIIIIIII7777777777777777777$$$MMM 27 | MM??????????????????????????????IIIIIIIIIIIIIIIIIIIII7777777777777777777$$$$$MMM 28 | MM??????????????????????????IIIIIIIIIIIIIIIIIIIIIII77777777777777777777$$$$$$MMM 29 | MM??????????????????????IIIIIIIIIIIIIIIIIIIIIIIIII777777777777777777$$$$$$$$$MMM 30 | MM?IIIIIIIIIIIIIIIIIIIIIIII,...........,IIIIIIIII777777777777777777$$$$$$$$$$MMM 31 | MMIIIIIIIIIIIIIIIIIIIIII,...............+IIIII777777777777777777$$$$$$$$$$$$$MMM 32 | MMIIIIIIIIIIIIIIIIIIII..................+III7777777777777777777$$$$$$$$$$$$$$MMM 33 | MMIIIIIIIIIIIIIIIIII?........?7IIIII777.?77777777777777777777$$$$$$$$$$$$$$$$MMM 34 | MMIIIIIIIIIIIIIIIIII.......IIIIIIIII777777777................$$$$$$$$$$$$$$$$MMM 35 | MMIIIIIIIIIIIIIIIII......+IIIIII7777777777777................I$$$$$$$$$$$$$$$MMM 36 | MMIIIIIIIIIIIIIIII.......77777777777777777777................~$$$$$$$$$$$$$$$MMM 37 | MMIIIIIIIIIIIIII7I......777777777777777777777......7$$$$$$$$$$$$$$$$$$$$$$ZZZMMM 38 | MM777777777777777=......777777777777777777777......$$$$$$$$$$$$$$$$$$$$ZZ$ZZZMMM 39 | MM777777777777777......+77777777777777777777$......$$$$$$$$$$$$$$$$$ZZZZZZZZZMMM 40 | MM777777777777777......I77777777777777777$$$$,...,,$$$$$$$$$$$$$$$ZZZZZZZZZZZMMM 41 | MM777777777777777......+777777777777$$$$$$$$$,,,,,,+++++++++7$$$ZZZZZZZZZZZZZMMM 42 | MM777777777777777.......77777$$$$$$$$$$$$$$$$,,,,,,,,,,,,,,,+ZZZZZZZZZZZZZZZZMMM 43 | MM777777777777777+......7$$$$$$$$$$$$$$$$$$$$,,,,,,,,,,,,,,,+ZZZZZZZZZZZZZZZOMMM 44 | MM777777777777777$..,,,,~$$$$$$$$$$$$$$$$$$$$,,,,,,?????????$ZZZZZZZZZZZZZZZZMMM 45 | MM$$$$$$$$$$$$$$$$.,,,,,,7$$$$$$$$$$$$$$$$$$$,,,,,,$ZZZZZZZZZZZZZZZZZZZZZZZZOMMM 46 | MM$$$$$$$$$$$$$$$$$.,,,,,,I$$$$$$$$$$$$$$$$$$,,,,,,ZZZZZZZZZZZZZZZZZZZZZZZZZOMMM 47 | MM$$$$$$$$$$$$$$$$$Z,,,,,,,,=$$$$$$$$$$$+ZZZZ,,,,,,ZZZZZZZZZZZZZZZZZZZZZZOOOOMMM 48 | MM$$$$$$$$$$$$$$$$$$Z,,,,,,,,,,,,,,,.,,,=ZZZZ,,,,,,ZZZZZZZZZZZZZZZZZZZOOOOOOOMMM 49 | MM$$$$$$$$$$$$$$$$$$$$:,,,,,,,,,,,,,,,,,=ZZZZ,,,,,,ZZZZZZZZZZZZZZOOZOOOOOOOOOMMM 50 | MM$$$$$$$$$$$$$$ZZZZZZZZ$,,,,,,,,,,,,,,,ZZZZZ,,,,,,ZZZZZZZZZZZOOOOOOOOOOOOOOOMMM 51 | MM$ZZZZZZZZZZZZZZZZZZZZZZZZZZ+,,,,,?ZZZZZZZZZOOOOOOOZZZZZOOOOOOOOOOOOOOOOOOOOMMM 52 | MM$ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZOOOOOOOOOOOOOOOOOOOOOOOOOMMM 53 | MM$ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZOOOOOOOOOOOOOOOOOOOOOOOOOOOOOMMM 54 | MMZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOMMM 55 | MMZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOMMM 56 | MMZZZZZZZZZZZZZZZZZZZZZOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO88MMM 57 | MMZZZZZZZOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO888888MMM 58 | MMZOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO888888888888MMM 59 | MMOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO88888888888888888MMM 60 | MMOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO88OO888888888888888888888MMM 61 | MMOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO8OOOO88888888888888888888888888888MMM 62 | MMOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO8OO8888888888888888888888888888888888888888MMM 63 | MM8OOOOOOOOOOOOOOOO8888888888888888888888888888888888888888888888888888888888MMM 64 | MM888888888888888888888888888888888888888888888888888888888888888888888888888MMM 65 | MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM 66 | MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM 67 | MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM 68 | MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM 69 | 70 | 71 | Hoth aims to help developers better understand exceptions--caught or not--in 72 | their application so you can prioritize resolution. Hoth is a simple but 73 | effective exception content tracking system. 74 | 75 | What does Hoth do? 76 | ------------------ 77 | Hoth can send you an alert when a new, unique exception occurs within your 78 | application. You only receive these alerts the first time an exception is seen 79 | by Hoth. 80 | 81 | 82 | 83 | Is that all Hoth does? 84 | ---------------------- 85 | Nope! It gets better. Hoth also tracks each occurrence so you can quickly 86 | understand how frequent an exception is within your app. No more hunting 87 | through log files that repeat messages over, and over. 88 | 89 | 90 | 91 | Why should you use Hoth? 92 | ------------------------ 93 | Hoth helps you analyze your errors so you can prioritize and fix them 94 | without hunting through log, after log, after log......after log. 95 | 96 | 97 | 98 | How do you use Hoth? 99 | -------------------- 100 | You can read about, and learn how to implement, Hoth by reading the blog 101 | post here: 102 | 103 | https://github.com/aarongreenlee/Hoth/wiki 104 | 105 | How can I see the Hoth report right away? 106 | ----------------------------------------- 107 | If you would like to see the Hoth Report you can view the example exceptions 108 | by following these steps: 109 | 110 | 1. Drop Hoth in your Web root--or--make a server mapping '/Hoth' 111 | 112 | 2. Copy the /Hoth/examples/ColdFusion/HothReportUI.cfc to your 113 | Web site in an accessible location. 114 | 115 | 3. Hit the following URL: 116 | http://yourwebsite.com/HothReportUI.cfc?method=index 117 | 118 | 4. You should now be looking at example Hoth exceptions. 119 | 120 | 121 | High-level, 50,000 ft. view of what you need to do... 122 | ----------------------------------------------------- 123 | There are two distinct parts to Hoth: Tracking and Reporting. 124 | 125 | Tracking 126 | -------- 127 | Tracking is common to all applications and very easy to set up. These 128 | instructions will apply to all applications. 129 | 130 | Reporting 131 | --------- 132 | Things become a little (but not a lot) more complex here. Reporting 133 | requires access to your server from a HTTP call. This is your responsibility 134 | to setup--and there are lots of paths you can take to implement reporting. 135 | 136 | If you take the path of using the HothReportUI.cfc you will definitely 137 | want to open that file and make some edits (like adding the path to 138 | your own HothConfig). 139 | 140 | 141 | ******************************************************************************** 142 | ******************************************************************************** 143 | ******************************************************************************** 144 | 145 | Authors: 146 | ------- 147 | Aaron Greenlee - http://aarongreenlee.com 148 | Sean Coyne - http://www.n42designs.com 149 | Dan Skaggs - http://TNTechnoHermit.com 150 | Mike Henke - http://www.henke.ws 151 | James Brown - http://coldfusioning.com 152 | Dave Shuck - http://daveshuck.com 153 | Greg Moser - http://www.gregmoser.com 154 | 155 | -------------------------------------------------------------------------------- 156 | 157 | Requirements 158 | 159 | Adobe ColdFusion 9.01 with HotFix 1 Applied 160 | 161 | Not yet tested on Railo or OpenBD. 162 | 163 | -------------------------------------------------------------------------------- 164 | Hoth License 165 | 166 | This file is part of Hoth. 167 | 168 | This work is licensed under a Creative Commons Attribution-Share-Alike 3.0 169 | Unported License. 170 | 171 | Hoth is Copyright 2011 Aaron Greenlee 172 | 173 | -------------------------------------------------------------------------------- 174 | Hoth has the following third-party dependencies or code included: 175 | 176 | MockBox (http://coldbox.org) 177 | MXUnit (http://mxunit.org) 178 | 179 | ******************************************************************************** 180 | ******************************************************************************** 181 | ******************************************************************************** 182 | 183 | Changelog: 184 | 02/09/2011 - The source was opened. 185 | 02/23/2011 - Merged the Bleeding branch. Users can now define their 186 | URL in their HothConfig.cfc. 187 | -------------------------------------------------------------------------------- /views/report.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exceptions Observed by Hoth 5 | 6 | 7 | 17 | 18 | 104 | 105 | 106 |

Visit the main site at http://aarongreenlee.com/hoth

107 |

Hoth: ColdFusion Exception Tracking

108 |
109 |
110 |

Exceptions

111 |
    112 |
    113 |
    114 |

    Details

    115 |
    Click an exception from the list on the left.
    116 |
    117 |
    118 | 119 | 239 | 240 | -------------------------------------------------------------------------------- /examples/CFWheels/views/hoth/report.cfm: -------------------------------------------------------------------------------- 1 | 2 | Exceptions Observed by Hoth 3 | 4 | 5 | 91 | 92 | 93 |

    Visit the main site at http://aarongreenlee.com/hoth

    94 |

    Hoth: ColdFusion Exception Tracking

    95 |
    96 |
    97 |

    Exceptions

    98 |
      99 |
      100 |
      101 |

      Details

      102 |
      Click an exception from the list on the left.
      103 |
      104 |
      105 | 106 | 255 | 256 | -------------------------------------------------------------------------------- /HothTracker.cfc: -------------------------------------------------------------------------------- 1 | /** 2 | Aaron Greenlee 3 | http://aarongreenlee.com/ 4 | 5 | This work is licensed under a Creative Commons Attribution-Share-Alike 3.0 6 | Unported License. 7 | 8 | // Original Info ----------------------------------------------------------- 9 | Author : Aaron Greenlee 10 | Created : 10/01/2010 11 | 12 | HothTracker is responsible for accepting a exception, tracking the frequency 13 | of the exception and alerting developers for new, unique exceptions. 14 | 15 | // Modifications :--------------------------------------------------------- 16 | Modified : 12/13/2010 9:52:41 AM by Aaron Greenlee. 17 | - Now supporting ColdBox 3.0 RC1 18 | */ 19 | component 20 | name='HothTracker' 21 | accessors=false 22 | { 23 | 24 | public Hoth.HothTracker function init (HothConfig) { 25 | // If a config object was not provided we 26 | // will use our default. 27 | variables.Config = (structKeyExists(arguments, 'HothConfig')) 28 | ? arguments.HothConfig 29 | : new Hoth.object.HothConfig(); 30 | 31 | VARIABLES._NAME = 'Hoth_' & variables.Config.getApplicationName(); 32 | 33 | variables.exceptionKeys = ['detail','type','tagcontext','stacktrace','message']; // Required exception keys 34 | variables.paths.LogPath = variables.Config.getLogPathExpanded(); // Get the root location for our logging. 35 | variables.paths.Exceptions = variables.Config.getPath('exceptions'); // Track the unique exceptions. 36 | variables.paths.Incidents = variables.Config.getPath('incidents'); // Track the hits per exception. 37 | variables.paths.Report = variables.Config.getPath('exceptionReport'); // The actual report 38 | variables.paths.Activity = variables.Config.getPath('exceptionReportActivity'); // Track when we save things. Helps understand volume. 39 | //variables.paths.Index = variables.Config.getPath('exceptionIndex'); // Tracks the exception keys to prevent duplication 40 | 41 | verifyDirectoryStructure(); 42 | 43 | try { 44 | // For the life of this HothTracker, keep the ApplicationManager. 45 | variables.HothApplicationManager = new Hoth.object.HothApplicationManager(HothConfig); 46 | // Because the entire application db file is locked, we only want to 47 | // learn about this application when the HothTracker is created. The 48 | // actual amount of work done within the manager is small, but, it is 49 | // does block all other processes for all other Hoth instances, so, we 50 | // want to reduce calls to it to this constructor. 51 | variables.HothApplicationManager.learnApplication(arguments.HothConfig); 52 | } catch (any e) { 53 | //writeDump(e);abort; 54 | } 55 | return this; 56 | } 57 | 58 | /** Track an exception. 59 | @ExceptionStructure A ColdFusion cfcatch or a supported object from a Framework or Application. */ 60 | public boolean function track (any Exception) { 61 | local.ExceptionStructure = parseException(arguments.Exception); 62 | 63 | // If we did not parse what we are supposed to 64 | // track, we will abort. 65 | if (!local.ExceptionStructure.validException) 66 | return false; 67 | 68 | // ------------------------------------------------------------------------------ 69 | try { 70 | // ------------------------------------------------------------------------------ 71 | local.e = { 72 | detail = structKeyExists(local.ExceptionStructure,'detail') ? local.ExceptionStructure.detail : '_noDetail' 73 | ,message = structKeyExists(local.ExceptionStructure,'message') ? local.ExceptionStructure.message : '_noMessage' 74 | ,stack = structKeyExists(local.ExceptionStructure,'stacktrace') ? local.ExceptionStructure.stacktrace : '_no_stacktrace' 75 | ,context = structKeyExists(local.ExceptionStructure,'tagcontext') ? local.ExceptionStructure.tagcontext : '_no_tagcontext' 76 | ,format = structKeyExists(local.ExceptionStructure,'format') ? local.ExceptionStructure.format: '_no_format' 77 | ,url = CGI.HTTP_HOST & CGI.path_info 78 | ,client = CGI.HTTP_USER_AGENT 79 | }; 80 | 81 | // Generate JSON for hashing 82 | local.json = {}; 83 | local.k = ''; 84 | for(local.k in local.e) 85 | local.json[k] = serializeJSON(local.e[local.k]); 86 | 87 | // Hash a unique key for the content of each property within the exception 88 | local.index = {}; 89 | local.index.stack = ( len(local.e.stack) > 0) ? hash(lcase(local.e.stack),'SHA') : '_no_stack'; 90 | local.index.key = lcase(local.index.stack); 91 | 92 | local.saveDetails = false; 93 | 94 | // Index the exception, count occurances and save details. 95 | // Lock is unique to the exception. 96 | lock name=local.index.key timeout=variables.Config.getTimeToLock() type="exclusive" { 97 | local.filename = local.index.key & '.log'; 98 | local.exceptionFile = variables.paths.Exceptions & '/' & local.filename; 99 | local.incidentsFile = variables.paths.Incidents & '/' & local.filename; 100 | 101 | local.exceptionIsKnown = fileExists(local.exceptionFile); 102 | 103 | if (!local.exceptionIsKnown) 104 | fileWrite(local.exceptionFile ,serializeJSON(local.e),'UTF-8'); 105 | 106 | // Create an incident if the file does not exist 107 | if (!fileExists(local.incidentsFile)) { 108 | fileWrite(local.incidentsFile ,now() & '#chr(13)#','UTF-8'); 109 | } else { 110 | local.file = fileOpen(local.incidentsFile,'append','utf-8'); 111 | fileWriteLine(local.file, now() & '|' & local.e.url ); 112 | fileClose(local.file); 113 | } 114 | } 115 | 116 | // Outside the lock, send mail if requested 117 | if (!local.exceptionIsKnown && variables.Config.getEmailNewExceptions() ) { 118 | 119 | local.INetAddress = createObject( 'java', 'java.net.InetAddress' ); 120 | 121 | local.url = (len(CGI.QUERY_STRING) > 0) 122 | ? CGI.http_host & CGI.path_info & '?' & Cgi.QUERY_STRING 123 | : CGI.http_host & CGI.path_info; 124 | 125 | local.emailBody = [ 126 | "Hoth tracked a new exception (" & local.index.key & ")." 127 | ,"Message: " & local.e.message 128 | ,"Machine Name: " & local.INetAddress.getLocalHost().getHostName() 129 | ,"Address: " & local.url 130 | ]; 131 | 132 | local.Mail = new Mail( subject='Hoth Exception (' & variables.Config.getApplicationName() & ') ' & local.index.key 133 | ,to=variables.Config.getEmailNewExceptionsTo() 134 | ,from=variables.Config.getEmailNewExceptionsFrom()); 135 | 136 | // Attach the file 137 | if ( variables.Config.getEmailNewExceptionsFile() ) { 138 | local.Mail.addParam(file=local.exceptionFile); 139 | ArrayAppend( local.emailBody, "To view the attached exception info, copy and paste into FireBug's console (x = exception) and press CRTL+Enter." ); 140 | } 141 | 142 | // Show exception as HTML inline? 143 | if ( variables.Config.getEmailExceptionsAsHTML() ) { 144 | local.Mail.setType( "html" ); 145 | savecontent variable="local.emailBody" { 146 | writeOutput( arrayToList( local.emailBody, "
      " ) ); 147 | writeOutput( "
      Exception Details:
      "); 148 | writeDump( local.e ); 149 | } 150 | local.Mail.setBody( local.emailBody ); 151 | } 152 | else { 153 | local.Mail.setBody( arrayToList( local.emailBody, "#chr(10)##chr(13)#" ) ); 154 | } 155 | 156 | local.mail.Send(); 157 | } 158 | // ------------------------------------------------------------------------------ 159 | } catch (any e) { 160 | return false; 161 | } 162 | // ------------------------------------------------------------------------------ 163 | return true; 164 | } 165 | 166 | // Private Methods Follow ------------------------------------------------------- 167 | /** Parse an exception provided by a framework or supported application. 168 | Hoth is easy to support. Just provide a Struct with at least the following keys: 169 | 'detail,type,tagContext,StackTrace,Message' 170 | Or an object with the same information that Hoth can extract. */ 171 | private struct function parseException(any Exception) { 172 | local.result = { validException = false }; 173 | 174 | // Return the meta data for our passed exception 175 | local.md = getMetaData(Exception); 176 | 177 | // Inspect the class tree to understand what type of object 178 | // we are working with. 179 | local.classTree = GetClassHeirarchy(local.md); 180 | 181 | // Was our object built with ColdFusion? If so, it is custom. 182 | // If not, the object is considered to be native and generated by CF. 183 | local.exceptionType = ( 184 | listContainsNoCase(local.classTree, 'coldfusion.runtime.AttributeCollection', ' ') 185 | ) ? 'Custom' : 'Native'; 186 | 187 | if (local.exceptionType == 'Native') 188 | { 189 | local.result.detail = (structKeyExists(arguments.Exception, 'detail')) ? arguments.Exception.detail : 'undefined'; 190 | local.result.message = (structKeyExists(arguments.Exception, 'message')) ? arguments.Exception.message : 'undefined'; 191 | local.result.stacktrace = (structKeyExists(arguments.Exception, 'stacktrace')) ? arguments.Exception.stacktrace : 'undefined'; 192 | local.result.tagcontext = (structKeyExists(arguments.Exception, 'tagContext')) ? arguments.Exception.tagContext : 'undefined'; 193 | local.result.validException = true; 194 | local.result.format = 'Native'; 195 | 196 | // ADDED by Benoit Hediard to get real detail and message in FW1 197 | if (local.result.message == "Event handler exception." && structKeyExists(arguments.Exception, "Cause")) { 198 | local.result.detail = (structKeyExists(arguments.Exception.Cause, 'detail')) ? arguments.Exception.Cause.detail : 'undefined'; 199 | local.result.message = (structKeyExists(arguments.Exception.Cause, 'message')) ? arguments.Exception.Cause.message : 'undefined'; 200 | }; 201 | return local.result; 202 | } else { 203 | //detail,type,tagcontext,stacktrace,message 204 | switch(local.md.fullname) { 205 | // ColdBox Excepiont 206 | case 'coldbox.system.beans.ExceptionBean' : 207 | case 'coldbox.system.web.context.ExceptionBean' : 208 | local.result.detail = arguments.Exception.getDetail(); 209 | local.result.message = arguments.Exception.getMessage(); 210 | local.result.stacktrace = arguments.Exception.getStackTrace(); 211 | local.result.tagcontext = arguments.Exception.getTagContext(); 212 | local.result.validException = true; 213 | local.result.format = 'ColdBox'; 214 | break; 215 | // Unknown Exception Passed 216 | default : 217 | local.result.validException = false; 218 | local.result.format = 'Unknown'; 219 | break; 220 | /*case 'MachII.util.Exception' : 221 | local.result = arguments.Exception.getCaughtException(); 222 | local.result.validException = true; 223 | break;*/ 224 | } 225 | } 226 | 227 | return local.result; 228 | } 229 | 230 | /** Inspect the class heirarchy to return a string showing the class tree. 231 | Original code is borrowed from Dominic Watson at the following address. 232 | Rewritten for for CF9+/Railo features. 233 | http://fusion.dominicwatson.co.uk/2007/09/coldfusion-objects-are-java-objects.html **/ 234 | private function GetClassHeirarchy(obj) { 235 | local.thisClass = obj.GetClass(); 236 | local.sReturn = thisClass.GetName(); 237 | 238 | do{ 239 | local.thisClass = local.thisClass.GetSuperClass(); 240 | local.sReturn &= " " & thisClass.GetName(); 241 | } while(CompareNoCase(thisClass.GetName(), 'java.lang.Object')); 242 | 243 | return local.sReturn; 244 | } 245 | 246 | /** Verify the desired directory structure exsits. */ 247 | private void function verifyDirectoryStructure() { 248 | // Verify our index diectory exists 249 | 250 | /* Ensure our directory structure is as expected. */ 251 | lock name=VARIABLES._NAME timeout=variables.Config.getTimeToLock() type="exclusive" { 252 | if (!directoryExists(variables.paths.Exceptions)) { 253 | directoryCreate(variables.paths.Exceptions); 254 | fileWrite(variables.paths.Exceptions & '/_readme.txt','Hoth: The files within this directory contain the complete details for each unique exception.'); 255 | } 256 | if (!directoryExists(variables.paths.Incidents)) { 257 | directoryCreate(variables.paths.Incidents); 258 | fileWrite(variables.paths.Incidents & '/_readme.txt','Hoth: The files within this directory contain the details about the volume of errors for each unique exception.'); 259 | } 260 | } 261 | 262 | return; 263 | } 264 | } 265 | -------------------------------------------------------------------------------- /examples/Example_Logs/exceptions/02E9D2BB4A77C0AA0EB521E376470603CEB6BC8B.log: -------------------------------------------------------------------------------- 1 | {"MESSAGE":"Connect Exception: Connection refused: connect","CLIENT":"Mozilla\/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit\/534.13 (KHTML, like Gecko) Chrome\/9.0.597.94 Safari\/534.13","FORMAT":[{"RAW_TRACE":"\tat cfSolrSearchGateway2ecfc1568756015$funcTRACKISSUE.runFunction(C:\\web\\bar\\shared\\models\\services\\search\\SolrSearchGateway.cfc:341)","ID":"CFTHROW","TEMPLATE":"C:\\web\\bar\\shared\\models\\services\\search\\SolrSearchGateway.cfc","LINE":341,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfSolrSearchGateway2ecfc1568756015$funcVERIFYRESULTS.runFunction(C:\\web\\bar\\shared\\models\\services\\search\\SolrSearchGateway.cfc:286)","ID":"CF_UDFMETHOD","TEMPLATE":"C:\\web\\bar\\shared\\models\\services\\search\\SolrSearchGateway.cfc","LINE":286,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfSolrSearchGateway2ecfc1568756015$funcSEARCH.runFunction(C:\\web\\bar\\shared\\models\\services\\search\\SolrSearchGateway.cfc:82)","ID":"CF_UDFMETHOD","TEMPLATE":"C:\\web\\bar\\shared\\models\\services\\search\\SolrSearchGateway.cfc","LINE":82,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfSolrSearchService2ecfc1232899747$funcSEARCHSOLRFROMCOLDFUSION.runFunction(C:\\web\\bar\\shared\\models\\services\\search\\SolrSearchService.cfc:412)","ID":"CF_TEMPLATEPROXY","TEMPLATE":"C:\\web\\bar\\shared\\models\\services\\search\\SolrSearchService.cfc","LINE":412,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfSolrSearchService2ecfc1232899747$funcSEARCH.runFunction(C:\\web\\bar\\shared\\models\\services\\search\\SolrSearchService.cfc:213)","ID":"CF_UDFMETHOD","TEMPLATE":"C:\\web\\bar\\shared\\models\\services\\search\\SolrSearchService.cfc","LINE":213,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfSearch2ecfc1496682932$funcV2.runFunction(C:\\web\\bar\\foobar\\handlers\\Search.cfc:318)","ID":"CF_TEMPLATEPROXY","TEMPLATE":"C:\\web\\bar\\foobar\\handlers\\Search.cfc","LINE":318,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfController2ecfc375683387$funcINVOKER.runFunction(C:\\web\\lib\\coldbox\\system\\web\\Controller.cfc:695)","ID":"CFINVOKE","TEMPLATE":"C:\\web\\lib\\coldbox\\system\\web\\Controller.cfc","LINE":695,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfController2ecfc375683387$funcRUNEVENT.runFunction(C:\\web\\lib\\coldbox\\system\\web\\Controller.cfc:582)","ID":"CF_UDFMETHOD","TEMPLATE":"C:\\web\\lib\\coldbox\\system\\web\\Controller.cfc","LINE":582,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfColdbox2ecfc204091051$funcPROCESSCOLDBOXREQUEST.runFunction(C:\\web\\lib\\coldbox\\system\\Coldbox.cfc:238)","ID":"CF_TEMPLATEPROXY","TEMPLATE":"C:\\web\\lib\\coldbox\\system\\Coldbox.cfc","LINE":238,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfApplication2ecfc749399233$funcONREQUESTSTART.runFunction(C:\\web\\bar\\foobar\\Application.cfc:112)","ID":"CF_UDFMETHOD","TEMPLATE":"C:\\web\\bar\\foobar\\Application.cfc","LINE":112,"TYPE":"CFML","COLUMN":0}],"STACK":"coldfusion.runtime.CustomException: Connect Exception: Connection refused: connect\r\n\tat coldfusion.tagext.lang.ThrowTag.doStartTag(ThrowTag.java:142)\r\n\tat coldfusion.runtime.CfJspPage._emptyTcfTag(CfJspPage.java:2722)\r\n\tat cfSolrSearchGateway2ecfc1568756015$funcTRACKISSUE.runFunction(C:\\web\\bar\\shared\\models\\services\\search\\SolrSearchGateway.cfc:341)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:472)\r\n\tat coldfusion.runtime.UDFMethod$ReturnTypeFilter.invoke(UDFMethod.java:405)\r\n\tat coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:368)\r\n\tat coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:55)\r\n\tat coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:321)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:517)\r\n\tat coldfusion.runtime.CfJspPage._invokeUDF(CfJspPage.java:2547)\r\n\tat cfSolrSearchGateway2ecfc1568756015$funcVERIFYRESULTS.runFunction(C:\\web\\bar\\shared\\models\\services\\search\\SolrSearchGateway.cfc:286)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:472)\r\n\tat coldfusion.runtime.UDFMethod$ReturnTypeFilter.invoke(UDFMethod.java:405)\r\n\tat coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:368)\r\n\tat coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:55)\r\n\tat coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:321)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:220)\r\n\tat coldfusion.runtime.CfJspPage._invokeUDF(CfJspPage.java:2582)\r\n\tat cfSolrSearchGateway2ecfc1568756015$funcSEARCH.runFunction(C:\\web\\bar\\shared\\models\\services\\search\\SolrSearchGateway.cfc:82)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:472)\r\n\tat coldfusion.runtime.UDFMethod$ReturnTypeFilter.invoke(UDFMethod.java:405)\r\n\tat coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:368)\r\n\tat coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:55)\r\n\tat coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:321)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:517)\r\n\tat coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:496)\r\n\tat coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:355)\r\n\tat coldfusion.runtime.CfJspPage._invoke(CfJspPage.java:2301)\r\n\tat cfSolrSearchService2ecfc1232899747$funcSEARCHSOLRFROMCOLDFUSION.runFunction(C:\\web\\bar\\shared\\models\\services\\search\\SolrSearchService.cfc:412)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:472)\r\n\tat coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:368)\r\n\tat coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:55)\r\n\tat coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:321)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:517)\r\n\tat coldfusion.runtime.CfJspPage._invokeUDF(CfJspPage.java:2547)\r\n\tat cfSolrSearchService2ecfc1232899747$funcSEARCH.runFunction(C:\\web\\bar\\shared\\models\\services\\search\\SolrSearchService.cfc:213)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:472)\r\n\tat coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:368)\r\n\tat coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:55)\r\n\tat coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:321)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:517)\r\n\tat coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:496)\r\n\tat coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:355)\r\n\tat coldfusion.runtime.CfJspPage._invoke(CfJspPage.java:2301)\r\n\tat cfSearch2ecfc1496682932$funcV2.runFunction(C:\\web\\bar\\foobar\\handlers\\Search.cfc:318)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:472)\r\n\tat coldfusion.runtime.UDFMethod$ReturnTypeFilter.invoke(UDFMethod.java:405)\r\n\tat coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:368)\r\n\tat coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:55)\r\n\tat coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:321)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:517)\r\n\tat coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:496)\r\n\tat coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:355)\r\n\tat coldfusion.runtime.CfJspPage._invoke(CfJspPage.java:2301)\r\n\tat coldfusion.tagext.lang.InvokeTag.doEndTag(InvokeTag.java:389)\r\n\tat coldfusion.runtime.CfJspPage._emptyTcfTag(CfJspPage.java:2723)\r\n\tat cfController2ecfc375683387$funcINVOKER.runFunction(C:\\web\\lib\\coldbox\\system\\web\\Controller.cfc:695)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:472)\r\n\tat coldfusion.filter.SilentFilter.invoke(SilentFilter.java:47)\r\n\tat coldfusion.runtime.UDFMethod$ReturnTypeFilter.invoke(UDFMethod.java:405)\r\n\tat coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:368)\r\n\tat coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:55)\r\n\tat coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:321)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:220)\r\n\tat coldfusion.runtime.CfJspPage._invokeUDF(CfJspPage.java:2582)\r\n\tat cfController2ecfc375683387$funcRUNEVENT.runFunction(C:\\web\\lib\\coldbox\\system\\web\\Controller.cfc:582)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:472)\r\n\tat coldfusion.filter.SilentFilter.invoke(SilentFilter.java:47)\r\n\tat coldfusion.runtime.UDFMethod$ReturnTypeFilter.invoke(UDFMethod.java:405)\r\n\tat coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:368)\r\n\tat coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:55)\r\n\tat coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:321)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:517)\r\n\tat coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:496)\r\n\tat coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:355)\r\n\tat coldfusion.runtime.CfJspPage._invoke(CfJspPage.java:2301)\r\n\tat cfColdbox2ecfc204091051$funcPROCESSCOLDBOXREQUEST.runFunction(C:\\web\\lib\\coldbox\\system\\Coldbox.cfc:238)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:472)\r\n\tat coldfusion.runtime.UDFMethod$ReturnTypeFilter.invoke(UDFMethod.java:405)\r\n\tat coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:368)\r\n\tat coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:55)\r\n\tat coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:321)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:220)\r\n\tat coldfusion.runtime.CfJspPage._invokeUDF(CfJspPage.java:2582)\r\n\tat cfApplication2ecfc749399233$funcONREQUESTSTART.runFunction(C:\\web\\bar\\foobar\\Application.cfc:112)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:472)\r\n\tat coldfusion.runtime.UDFMethod$ReturnTypeFilter.invoke(UDFMethod.java:405)\r\n\tat coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:368)\r\n\tat coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:55)\r\n\tat coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:321)\r\n\tat coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:220)\r\n\tat coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:491)\r\n\tat coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:337)\r\n\tat coldfusion.runtime.AppEventInvoker.invoke(AppEventInvoker.java:88)\r\n\tat coldfusion.runtime.AppEventInvoker.onRequestStart(AppEventInvoker.java:258)\r\n\tat coldfusion.filter.ApplicationFilter.invoke(ApplicationFilter.java:349)\r\n\tat coldfusion.filter.RequestMonitorFilter.invoke(RequestMonitorFilter.java:48)\r\n\tat coldfusion.filter.MonitoringFilter.invoke(MonitoringFilter.java:40)\r\n\tat coldfusion.filter.PathFilter.invoke(PathFilter.java:94)\r\n\tat coldfusion.filter.LicenseFilter.invoke(LicenseFilter.java:27)\r\n\tat coldfusion.filter.ExceptionFilter.invoke(ExceptionFilter.java:70)\r\n\tat coldfusion.filter.ClientScopePersistenceFilter.invoke(ClientScopePersistenceFilter.java:28)\r\n\tat coldfusion.filter.BrowserFilter.invoke(BrowserFilter.java:38)\r\n\tat coldfusion.filter.NoCacheFilter.invoke(NoCacheFilter.java:46)\r\n\tat coldfusion.filter.GlobalsFilter.invoke(GlobalsFilter.java:38)\r\n\tat coldfusion.filter.DatasourceFilter.invoke(DatasourceFilter.java:22)\r\n\tat coldfusion.filter.CachingFilter.invoke(CachingFilter.java:62)\r\n\tat coldfusion.CfmServlet.service(CfmServlet.java:200)\r\n\tat coldfusion.bootstrap.BootstrapServlet.service(BootstrapServlet.java:89)\r\n\tat jrun.servlet.FilterChain.doFilter(FilterChain.java:86)\r\n\tat com.intergral.fusionreactor.filter.FusionReactorFilter.b(FusionReactorFilter.java:376)\r\n\tat com.intergral.fusionreactor.filter.FusionReactorFilter.c(FusionReactorFilter.java:254)\r\n\tat com.intergral.fusionreactor.filter.FusionReactorFilter.doFilter(FusionReactorFilter.java:164)\r\n\tat jrun.servlet.FilterChain.doFilter(FilterChain.java:94)\r\n\tat coldfusion.monitor.event.MonitoringServletFilter.doFilter(MonitoringServletFilter.java:42)\r\n\tat coldfusion.bootstrap.BootstrapFilter.doFilter(BootstrapFilter.java:46)\r\n\tat jrun.servlet.FilterChain.doFilter(FilterChain.java:94)\r\n\tat jrun.servlet.FilterChain.service(FilterChain.java:101)\r\n\tat jrun.servlet.ServletInvoker.invoke(ServletInvoker.java:106)\r\n\tat jrun.servlet.JRunInvokerChain.invokeNext(JRunInvokerChain.java:42)\r\n\tat jrun.servlet.JRunRequestDispatcher.invoke(JRunRequestDispatcher.java:286)\r\n\tat jrun.servlet.ServletEngineService.dispatch(ServletEngineService.java:543)\r\n\tat jrun.servlet.jrpp.JRunProxyService.invokeRunnable(JRunProxyService.java:203)\r\n\tat jrunx.scheduler.ThreadPool$DownstreamMetrics.invokeRunnable(ThreadPool.java:320)\r\n\tat jrunx.scheduler.ThreadPool$ThreadThrottle.invokeRunnable(ThreadPool.java:428)\r\n\tat jrunx.scheduler.ThreadPool$UpstreamMetrics.invokeRunnable(ThreadPool.java:266)\r\n\tat jrunx.scheduler.WorkerThread.run(WorkerThread.java:66)\r\n","DETAIL":"Solr did not respond when connecting to '10.101.0.137'","URL":"some.com\/search\/","CONTEXT":[{"RAW_TRACE":"\tat cfSolrSearchGateway2ecfc1568756015$funcTRACKISSUE.runFunction(C:\\web\\bar\\shared\\models\\services\\search\\SolrSearchGateway.cfc:341)","ID":"CFTHROW","TEMPLATE":"C:\\web\\bar\\shared\\models\\services\\search\\SolrSearchGateway.cfc","LINE":341,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfSolrSearchGateway2ecfc1568756015$funcVERIFYRESULTS.runFunction(C:\\web\\bar\\shared\\models\\services\\search\\SolrSearchGateway.cfc:286)","ID":"CF_UDFMETHOD","TEMPLATE":"C:\\web\\bar\\shared\\models\\services\\search\\SolrSearchGateway.cfc","LINE":286,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfSolrSearchGateway2ecfc1568756015$funcSEARCH.runFunction(C:\\web\\bar\\shared\\models\\services\\search\\SolrSearchGateway.cfc:82)","ID":"CF_UDFMETHOD","TEMPLATE":"C:\\web\\bar\\shared\\models\\services\\search\\SolrSearchGateway.cfc","LINE":82,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfSolrSearchService2ecfc1232899747$funcSEARCHSOLRFROMCOLDFUSION.runFunction(C:\\web\\bar\\shared\\models\\services\\search\\SolrSearchService.cfc:412)","ID":"CF_TEMPLATEPROXY","TEMPLATE":"C:\\web\\bar\\shared\\models\\services\\search\\SolrSearchService.cfc","LINE":412,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfSolrSearchService2ecfc1232899747$funcSEARCH.runFunction(C:\\web\\bar\\shared\\models\\services\\search\\SolrSearchService.cfc:213)","ID":"CF_UDFMETHOD","TEMPLATE":"C:\\web\\bar\\shared\\models\\services\\search\\SolrSearchService.cfc","LINE":213,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfSearch2ecfc1496682932$funcV2.runFunction(C:\\web\\bar\\foobar\\handlers\\Search.cfc:318)","ID":"CF_TEMPLATEPROXY","TEMPLATE":"C:\\web\\bar\\foobar\\handlers\\Search.cfc","LINE":318,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfController2ecfc375683387$funcINVOKER.runFunction(C:\\web\\lib\\coldbox\\system\\web\\Controller.cfc:695)","ID":"CFINVOKE","TEMPLATE":"C:\\web\\lib\\coldbox\\system\\web\\Controller.cfc","LINE":695,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfController2ecfc375683387$funcRUNEVENT.runFunction(C:\\web\\lib\\coldbox\\system\\web\\Controller.cfc:582)","ID":"CF_UDFMETHOD","TEMPLATE":"C:\\web\\lib\\coldbox\\system\\web\\Controller.cfc","LINE":582,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfColdbox2ecfc204091051$funcPROCESSCOLDBOXREQUEST.runFunction(C:\\web\\lib\\coldbox\\system\\Coldbox.cfc:238)","ID":"CF_TEMPLATEPROXY","TEMPLATE":"C:\\web\\lib\\coldbox\\system\\Coldbox.cfc","LINE":238,"TYPE":"CFML","COLUMN":0},{"RAW_TRACE":"\tat cfApplication2ecfc749399233$funcONREQUESTSTART.runFunction(C:\\web\\bar\\foobar\\Application.cfc:112)","ID":"CF_UDFMETHOD","TEMPLATE":"C:\\web\\bar\\foobar\\Application.cfc","LINE":112,"TYPE":"CFML","COLUMN":0}]} --------------------------------------------------------------------------------