├── 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 |
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 |
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 |
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}]}
--------------------------------------------------------------------------------