#method()#` calls. +- Better error handling when Debugger assets are not compiled instead of a cryptic error message: +`The parameter [str] to function [closure_m] is required but was not passed in.` + ## [4.1.0] - 2023-04-17 ### Added -- New github actions -- Donot enable debugger in testing mode +- New github actions +- Donot enable debugger in testing mode ## [4.0.1] => 2022-NOV-22 ### Fixed -- Adobe dumb array by value +- Adobe dumb array by value ## [4.0.0] => 2022-NOV-22 ### Added -- ColdBox 7 support -- New `TimerDelegate` that can be used to add timer functions to any model -- Timer service rewritten to support nesting and included metadata -- Ability to open views and layouts from the execution timers in any Code Editor -- New `WireBoxCollector` which is only used if enabled. This greatly accelerates the performance of the request collector since before they where in the same collector. -- Ability to open CFCs that are profiled by the WireBox Collector in any Code Editor. -- Ability to open the Handler events that are profiled by the Request Collector in any Code Editor. -- New life-cycle events: `onDebuggerUnload`, `onDebuggerLoad` -- Ability for the custom `timeIt()` functions to accept metdata to store in the execution timer -- New `Slowest` Queries panel for cborm, acf, and qb/quick -- New visualizer total db time as well as request time including percentage of the request time -- Ability to export a profiler in json -- Ability to sort the visualizer's profilers +- ColdBox 7 support +- New `TimerDelegate` that can be used to add timer functions to any model: + - `startCBTimer()` + - `stopCBTimer()` + - `cbTimeIt()` + - `addCBTimer()` +- Timer service rewritten to support nesting and included metadata +- Ability to open views and layouts from the execution timers in any Code Editor +- New `WireBoxCollector` which is only used if enabled. This greatly accelerates the performance of the request collector since before they where in the same collector. +- Ability to open CFCs that are profiled by the WireBox Collector in any Code Editor. +- Ability to open the Handler events that are profiled by the Request Collector in any Code Editor. +- New life-cycle events: `onDebuggerUnload`, `onDebuggerLoad` +- Ability for the custom `timeIt()` functions to accept metdata to store in the execution timer +- New `Slowest` Queries panel for cborm, acf, and qb/quick +- New visualizer total db time as well as request time including percentage of the request time +- Ability to export a profiler in json +- Ability to sort the visualizer's profilers ### Fixed -- Timer service reconstructing the timer hashes and profilers twice. -- `timeIt()` helper was not passing the closure correctly -- If doing a fwreinit on the visualizer, the current profiler was still being show even thought it was empty. Add an empty check to avoid the big bang! -- Empty response codes for Adobe, due to their incredibly weird Response object nesting. -- Migration to java random id's for speed +- Timer service reconstructing the timer hashes and profilers twice. +- `timeIt()` helper was not passing the closure correctly +- If doing a fwreinit on the visualizer, the current profiler was still being show even thought it was empty. Add an empty check to avoid the big bang! +- Empty response codes for Adobe, due to their incredibly weird Response object nesting. +- Migration to java random id's for speed ### Changed -- Tracers are now streamlined and stored alongside the request profilers -- Small UI fixes on request profiler HTTP methods -- WireBox collecting is now done by the WireBox collector not the Request Collector. -- Adobe 2016 Dropped +- Tracers are now streamlined and stored alongside the request profilers +- Small UI fixes on request profiler HTTP methods +- WireBox collecting is now done by the WireBox collector not the Request Collector. +- Adobe 2016 Dropped ## [3.4.1] => 2022-JUL-12 ### Fixed -- If the debugger is disabled or not in debug mode, the panels and visualizers are still being rendered and exploding. This should be a 404. +- If the debugger is disabled or not in debug mode, the panels and visualizers are still being rendered and exploding. This should be a 404. ## [3.4.0] => 2022-JUN-27 ### Added -- Upgraded entire front end build process to ColdBox Elixir v4 -- Upgraded to Node 16 for all front end processes +- Upgraded entire front end build process to ColdBox Elixir v4 +- Upgraded to Node 16 for all front end processes ### Fixed -- If the cbdebugger was embedded within an app already using Alpine, it will fail. Now it will leach on to the running Alpine app. +- If the cbdebugger was embedded within an app already using Alpine, it will fail. Now it will leach on to the running Alpine app. ## [3.3.2] => 2022-MAY-02 ### Fixed -- [CBDEBUGGER-19](https://ortussolutions.atlassian.net/browse/CBDEBUGGER-19) - JSON Form serialization not working on formatting. +- [CBDEBUGGER-19](https://ortussolutions.atlassian.net/browse/CBDEBUGGER-19) - JSON Form serialization not working on formatting. ## [3.3.1] => 2022-APR-21 ### Fixed -- [CBDEBUGGER-17](https://ortussolutions.atlassian.net/browse/CBDEBUGGER-17) If you change the monitor frequency, it does not clear the old monitor and you get n monitors -- [CBDEBUGGER-16](https://ortussolutions.atlassian.net/browse/CBDEBUGGER-16) Left double hash on no state for request tracker profiler -- [CBDEBUGGER-15](https://ortussolutions.atlassian.net/browse/CBDEBUGGER-15) Auto-Refresh is not working in latest version -- [CBDEBUGGER-10](https://ortussolutions.atlassian.net/browse/CBDEBUGGER-10) Executing Event That Uses QB From Interceptor Generates CBDebugger Exception -- [CBDEBUGGER-6](https://ortussolutions.atlassian.net/browse/CBDEBUGGER-6) Stop auto-refresh when visiting a actual request report +- [CBDEBUGGER-17](https://ortussolutions.atlassian.net/browse/CBDEBUGGER-17) If you change the monitor frequency, it does not clear the old monitor and you get n monitors +- [CBDEBUGGER-16](https://ortussolutions.atlassian.net/browse/CBDEBUGGER-16) Left double hash on no state for request tracker profiler +- [CBDEBUGGER-15](https://ortussolutions.atlassian.net/browse/CBDEBUGGER-15) Auto-Refresh is not working in latest version +- [CBDEBUGGER-10](https://ortussolutions.atlassian.net/browse/CBDEBUGGER-10) Executing Event That Uses QB From Interceptor Generates CBDebugger Exception +- [CBDEBUGGER-6](https://ortussolutions.atlassian.net/browse/CBDEBUGGER-6) Stop auto-refresh when visiting a actual request report ## [3.3.0] => 2022-APR-21 ### Added -- Asynchronous saving of storage at end of requests -- Asynchronous size checks of storage -- Free memory diff in the visualizers -- Ability for each profiler to track how much memory they used during the course of the transaction by analyzing free memory -- New setting `requestPanelDock` to show/hide the request panel in the dock -- Migration to use new module template approaches that supports github releases, compilation and more -- Exception bean delegations in debugger service to avoid multi-instantiations `performance` -- Refactoring to increase `performance` and reusability -- Migration to AlpineJS from jquery -- New `sqlformatter` module from @michaelborn -- Updated to faster wasy to get a local ip and local hostname +- Asynchronous saving of storage at end of requests +- Asynchronous size checks of storage +- Free memory diff in the visualizers +- Ability for each profiler to track how much memory they used during the course of the transaction by analyzing free memory +- New setting `requestPanelDock` to show/hide the request panel in the dock +- Migration to use new module template approaches that supports github releases, compilation and more +- Exception bean delegations in debugger service to avoid multi-instantiations `performance` +- Refactoring to increase `performance` and reusability +- Migration to AlpineJS from jquery +- New `sqlformatter` module from @michaelborn +- Updated to faster wasy to get a local ip and local hostname ### Fixed -- Actually show a 404 if debug mode is off -- JS Bumps +- Actually show a 404 if debug mode is off +- JS Bumps ### Removed -- Reload all modules. Makes no sense as you can just reinit. +- Reload all modules. Makes no sense as you can just reinit. ## [3.2.0] => 2021-JUL-21 ### Changed -- Thanks to @homestar9 changed the elixir asset to a specific of `cbdebugger.(js.css)` to avoid collisions with main app. +- Thanks to @homestar9 changed the elixir asset to a specific of `cbdebugger.(js.css)` to avoid collisions with main app. ### Added -- Adobe 2021 support and automated testing -- Migration to github actions +- Adobe 2021 support and automated testing +- Migration to github actions ## [3.1.1] => 2021-JUN-05 ### Fixed -- Do not render when the request's content type is NOT html +- Do not render when the request's content type is NOT html ## [3.1.0] => 2021-MAy-19 ### Fixed -- Fix wrong cborm reference on QBCollector -- Look at the renderdata content type instead of type as it's more consistent in order to turn off the debugger on multi-marshalled sites -- [CBDEBUGGER-1] - Lucee debugger no longer shows below the cbDebugger. Turn off only on Ajax Calls +- Fix wrong cborm reference on QBCollector +- Look at the renderdata content type instead of type as it's more consistent in order to turn off the debugger on multi-marshalled sites +- [CBDEBUGGER-1] - Lucee debugger no longer shows below the cbDebugger. Turn off only on Ajax Calls ### Changed -- Use Java property for version to work with jdk8+ -- [CBDEBUGGER-2] - Made `cborm` and `qb` disabled by default +- Use Java property for version to work with jdk8+ +- [CBDEBUGGER-2] - Made `cborm` and `qb` disabled by default ## [3.0.0] => 2021-APR-07 ### Added -- Completely rewritten debugger -- Updated tracers to match all logbox options so we can use them for display instead of hardcoding them in the push operation -- Complete migration to elixir for assets -- Complete migration to runnable events to make things easier for rendering and debugging -- New interceptor profiling via AOP `announce` interceptions -- New object profiling via metadata AOP aspects via new settings: `profileObjects`, `traceObjectResults` -- New visualizer route `/cbdebugger` that if you are in debug mode, you can visualize the panels. Great for API apps -- New method: `timer.timeIt()` so you can time code execution via a closure wrapper -- New Helper Methods: `startCBTimer(), stopCBTimer(), cbTimeIt()` -- Added the route record to the info panel so you can debug the selected route -- Highlights transactions that take over `200ms` or using the `slowExecutionThreshold` setting -- Refactored to use array of structs instead of queries for even faster timer performance +- Completely rewritten debugger +- Updated tracers to match all logbox options so we can use them for display instead of hardcoding them in the push operation +- Complete migration to elixir for assets +- Complete migration to runnable events to make things easier for rendering and debugging +- New interceptor profiling via AOP `announce` interceptions +- New object profiling via metadata AOP aspects via new settings: `profileObjects`, `traceObjectResults` +- New visualizer route `/cbdebugger` that if you are in debug mode, you can visualize the panels. Great for API apps +- New method: `timer.timeIt()` so you can time code execution via a closure wrapper +- New Helper Methods: `startCBTimer(), stopCBTimer(), cbTimeIt()` +- Added the route record to the info panel so you can debug the selected route +- Highlights transactions that take over `200ms` or using the `slowExecutionThreshold` setting +- Refactored to use array of structs instead of queries for even faster timer performance ### Changed -- Encapsualted request timers UI into a single template -- `Timer` is now built in script and optimized -- Show timers as they start instead of how they end, huge UI update to visualize the timers -- Refactored the logbox appenders from `includes/appenders` to `appenders` +- Encapsualted request timers UI into a single template +- `Timer` is now built in script and optimized +- Show timers as they start instead of how they end, huge UI update to visualize the timers +- Refactored the logbox appenders from `includes/appenders` to `appenders` ### Security -- `Dumpar` facilities removed due to security concerns +- `Dumpar` facilities removed due to security concerns ### Removed -- Old `debugger` settings instead use the `modulesettings.cbdebugger` according to ColdBox 5+ standards -- Old helper code to remove helpers -- Removed the loaded modules as it just produced noise -- Removed the rc/prc snapshot comparisons, causes too much noise and not helpful anymore +- Old `debugger` settings instead use the `modulesettings.cbdebugger` according to ColdBox 5+ standards +- Old helper code to remove helpers +- Removed the loaded modules as it just produced noise +- Removed the rc/prc snapshot comparisons, causes too much noise and not helpful anymore ## [2.2.0] => 2020-MAY-18 ### Added -- Upgraded Appender to script and fixes for LogBox 6 -- More tests for logbox loading and appender registration +- Upgraded Appender to script and fixes for LogBox 6 +- More tests for logbox loading and appender registration ### Fixed -- Visual display of the debugger version +- Visual display of the debugger version ## [2.1.0] => 2020-MAY-14 ### Added -- ColdBox 6 support -- Formatting +- ColdBox 6 support +- Formatting ## Removed -- ColdBox 4 lingering code +- ColdBox 4 lingering code ## [2.0.0] => 2020-MAY-04 ### Added -- Formatting updates -- Quick/QB Panels +- Formatting updates +- Quick/QB Panels ### Removed -- Dropped ACF 11 support +- Dropped ACF 11 support ## [1.7.1] => 2019-MAR-06 -- Updated location protocol +- Updated location protocol ## [1.7.0] => 2019-MAR-06 -- Missing interception points for extending the panels: `afterDebuggerPanel`, `beforeDebuggerPanel` -- New Module Layout -- Dropping lucee 4.5 support +- Missing interception points for extending the panels: `afterDebuggerPanel`, `beforeDebuggerPanel` +- New Module Layout +- Dropping lucee 4.5 support ## [1.6.0 ] -- ColdBox 5 Support +- ColdBox 5 Support ## [1.5.0] -- Case-Sensitive filesystems fix -- Updated travis builds -- Unified workbench approach +- Case-Sensitive filesystems fix +- Updated travis builds +- Unified workbench approach ## [1.4.0] -- ColdBox Tracer Appender added by Default by Eric Peterson +- ColdBox Tracer Appender added by Default by Eric Peterson ## [1.3.0] -- Travis integration -- DocBox update -- Build process update +- Travis integration +- DocBox update +- Build process update ## [1.2.0] -- Fix unscoped currentrow which was throwing an error when debugging was enabled. -- Removed reference to missing images in CSS -- Updated build scripts -- How to turn off debugger for tests, it does this automatically now. -- filename cases don't match #5 on certain includes +- Fix unscoped currentrow which was throwing an error when debugging was enabled. +- Removed reference to missing images in CSS +- Updated build scripts +- How to turn off debugger for tests, it does this automatically now. +- filename cases don't match #5 on certain includes ## [1.1.0] --
+ * "debuggingDBEnabled":"true", + * "debuggingEnabled":"true", + * "debuggingQueryUsageEnabled":"false", // Extra Info + *+ */ +component extends="coldbox.system.Interceptor" { + + // DI + property name="debuggerService" inject="debuggerService@cbdebugger"; + property name="debuggerConfig" inject="coldbox:moduleSettings:cbdebugger"; + + /** + * Listen to when the tracker gets created + */ + function onDebuggerRequestTrackerCreation( event, interceptData, rc, prc ){ + // prep collector + arguments.interceptData.requestTracker[ "cfQueries" ] = { + "all" : [], + "grouped" : {}, + "totalQueries" : 0, + "totalExecutionTime" : 0 + }; + } + + /** + * Listen when request tracker is being recorded + */ + function onDebuggerProfilerRecording( event, interceptData, rc, prc ){ + var requestTracker = arguments.interceptData.requestTracker; + + // Get the query tracker data + requestTracker.cfQueries.all = getPageContext() + .getDebugger() + .getQueries() + .map( ( row ) => { + return { + "startTime" : row.getStartTime(), + "datasource" : row.getDatasource(), + "recordCount" : row.getRecordCount(), + "executionTime" : row.getExecutionTime(), + "sql" : variables.debuggerConfig.luceeSQL.logParams ? row.getSql().toString() : row + .getSql() + .getSqlString(), + "src" : row.getTemplateLine().toString() + } + } ); + + // Process grouped sql + requestTracker.cfQueries.all.each( ( row ) => { + var sqlHash = hash( row.sql ); + + if ( !requestTracker.cfQueries.grouped.keyExists( sqlHash ) ) { + requestTracker.cfQueries.grouped[ sqlHash ] = { "sql" : row.sql, "count" : 0, "records" : [] }; + } + + requestTracker.cfqueries.grouped[ sqlHash ].count++; + requestTracker.cfqueries.grouped[ sqlHash ].records.append( row ); + } ); + + // Store total number of queries executed + requestTracker.cfQueries[ "totalQueries" ] = requestTracker.cfQueries.all.len(); + requestTracker.cfQueries[ "totalExecutionTime" ] = requestTracker.cfQueries.all.reduce( ( total, q ) => arguments.total + ( arguments.q.executionTime ), 0 ); + } + +} diff --git a/interceptors/RequestCollector.cfc b/interceptors/RequestCollector.cfc index ce7d97b..318a331 100755 --- a/interceptors/RequestCollector.cfc +++ b/interceptors/RequestCollector.cfc @@ -82,12 +82,12 @@ component extends="coldbox.system.Interceptor" { // Record the profiler with the last tickcount variables.debuggerService.recordProfiler( event: arguments.event, executionTime: getTickCount() ); - // Determine if we can render the debugger at the bottom of the request + // Determine if we can render the request panel at the bottom of the request if ( - // Is the debugger turned on - variables.debuggerService.getDebugMode() AND // Can we show the end of request dock variables.debuggerConfig.requestPanelDock AND + // Is the debugger turned on + variables.debuggerService.getDebugMode() AND // Has it not been disabled by the user programmatically arguments.event.getPrivateValue( "cbox_debugger_show", true ) AND // Don't render in ajax calls @@ -102,7 +102,7 @@ component extends="coldbox.system.Interceptor" { !findNoCase( "MockController", getMetadata( controller ).name ) ) { // render out the debugger to the buffer output - arguments.buffer.append( runEvent( "cbdebugger:main.renderDebugger" ) ); + arguments.buffer.append( runEvent( "cbdebugger:main.renderRequestPanelDock" ) ); } } diff --git a/layouts/Main.cfm b/layouts/Dock.cfm similarity index 95% rename from layouts/Main.cfm rename to layouts/Dock.cfm index 104b3b9..00e1fd9 100644 --- a/layouts/Main.cfm +++ b/layouts/Dock.cfm @@ -7,7 +7,7 @@ x-data = "{ appUrl : '#encodeForJavaScript( event.buildLink( '' ) )#' }" - class="cbd-debugger" + class="cbd-debugger cbd-dock" id="cbd-debugger" data-appurl="#event.buildLink( '' )#" > diff --git a/layouts/Monitor.cfm b/layouts/Visualizer.cfm similarity index 100% rename from layouts/Monitor.cfm rename to layouts/Visualizer.cfm diff --git a/models/DebuggerService.cfc b/models/DebuggerService.cfc index aafe1ad..0870b62 100755 --- a/models/DebuggerService.cfc +++ b/models/DebuggerService.cfc @@ -20,8 +20,7 @@ component property name="asyncManager" inject="coldbox:asyncManager"; property name="interceptorService" inject="coldbox:interceptorService"; property name="timerService" inject="provider:Timer@cbdebugger"; - property name="jsonFormatter" inject="provider:JSONPrettyPrint@JSONPrettyPrint"; - property name="sqlFormatter" inject="provider:Formatter@sqlformatter"; + property name="formatter" inject="provider:Formatter@cbdebugger"; /** * -------------------------------------------------------------------------- @@ -191,32 +190,31 @@ component */ struct function createRequestTracker( required event ){ // Init the request debugger tracking - param request.cbDebugger = { - "coldbox" : {}, - "exception" : {}, - "executionTime" : 0, - "endFreeMemory" : 0, - "formData" : serializeJSON( form ?: {} ), - "fullUrl" : arguments.event.getFullUrl(), - "httpHost" : cgi.HTTP_HOST, - "httpReferer" : cgi.HTTP_REFERER, - "id" : variables.uuid.randomUUID().toString(), - "inetHost" : discoverInetHost(), - "ip" : getRealIP(), - "localIp" : getServerIp(), - "queryString" : cgi.QUERY_STRING, - "requestData" : getHTTPRequestData( - variables.debuggerConfig.requestTracker.httpRequest.profileHTTPBody - ), - "response" : { "statusCode" : 0, "contentType" : "" }, - "startCount" : getTickCount(), - "startFreeMemory" : variables.jvmRuntime.freeMemory(), - "threadInfo" : getCurrentThread().toString(), - "timers" : [], - "timestamp" : now(), - "tracers" : [], - "userAgent" : cgi.HTTP_USER_AGENT - }; + param request.cbDebugger = {}; + param request.cbDebugger.coldbox = {}; + param request.cbDebugger.exception = {}; + param request.cbDebugger.executionTime = 0; + param request.cbDebugger.endFreeMemory = 0; + param request.cbDebugger.formData = serializeJSON( form ?: {} ); + param request.cbDebugger.fullUrl = arguments.event.getFullUrl(); + param request.cbDebugger.httpHost = cgi.HTTP_HOST; + param request.cbDebugger.httpReferer = cgi.HTTP_REFERER; + param request.cbDebugger.id = variables.uuid.randomUUID().toString(); + param request.cbDebugger.inetHost = discoverInetHost(); + param request.cbDebugger.ip = getRealIP(); + param request.cbDebugger.localIp = getServerIp(); + param request.cbDebugger.queryString = cgi.QUERY_STRING; + param request.cbDebugger.requestData = getHTTPRequestData( + variables.debuggerConfig.requestTracker.httpRequest.profileHTTPBody + ); + param request.cbDebugger.response = { "statusCode" : 0, "contentType" : "" }; + param request.cbDebugger.startCount = getTickCount(); + param request.cbDebugger.startFreeMemory = variables.jvmRuntime.freeMemory(); + param request.cbDebugger.threadInfo = getCurrentThread().toString(); + param request.cbDebugger.timers = []; + param request.cbDebugger.timestamp = now(); + param request.cbDebugger.tracers = []; + param request.cbDebugger.userAgent = cgi.HTTP_USER_AGENT; // Event before recording variables.interceptorService.announce( @@ -593,6 +591,19 @@ component return getCurrentThread().getName(); } + /** + * Converts epoch milliseconds to a date time object + * + * @epoch The epoch to convert, must be in milliseconds + */ + function fromEpoch( required epoch ){ + return dateAdd( + "s", + arguments.epoch / 1000, + dateConvert( "utc2local", "January 1 1970 00:00 " ) + ); + } + /** * Process Stack trace for errors * @@ -608,11 +619,18 @@ component * Compose a screen for a file to open in an editor * * @event The request context - * @instance An instance of a tag context array + * @instance An instance of a tag context array { template, line } * * @return The string for the IDE */ - function openInEditorURL( required event, required struct instance ){ + function openInEditorURL( required event, required instance ){ + if ( isSimpleValue( arguments.instance ) ) { + arguments.instance = { + template : arguments.instance.getToken( 1, ":" ), + line : arguments.instance.getToken( 2, ":" ) + }; + } + return getExceptionBean().openInEditorURL( argumentCollection = arguments ); } diff --git a/models/Formatter.cfc b/models/Formatter.cfc new file mode 100644 index 0000000..edc9924 --- /dev/null +++ b/models/Formatter.cfc @@ -0,0 +1,109 @@ +/** + * Basic sql + json formatter + * This will be removed once CB7 is the default, since it's included in the core. + */ +component singleton { + + variables.NEW_LINE = chr( 13 ) & chr( 10 ); + variables.TAB = chr( 9 ); + + /** + * Format an incoming sql string to a pretty version + * + * @target The target sql to prettify + * + * @return The prettified sql + */ + function prettySql( string target = "" ){ + var keywords = [ + "ALTER TABLE", + "CREATE TABLE", + "DELETE", + "DROP TABLE", + "FROM", + "GROUP BY", + "HAVING", + "INSERT INTO", + "LIMIT", + "ORDER BY", + "OFFSET", + "SELECT", + "UNION", + "UPDATE", + "WHERE" + ]; + var indentedKeywords = [ + "FULL JOIN", + "INNER JOIN", + "JOIN", + "LEFT JOIN", + "OUTER JOIN" + ]; + var indent = " "; + + return arguments.target + .listToArray( variables.NEW_LINE ) + .map( ( item ) => item.trim() ) + // comma spacing + .map( ( item ) => item.reReplace( + "\s*(?![^()]*\))(,)\s*", + ",#variables.NEW_LINE##indent#", + "all" + ) ) + // Parenthesis spacing + .map( ( item ) => item.reReplace( "\((\w)", "( \1", "all" ) ) + .map( ( item ) => item.reReplace( "(\w)\)", "\1 )", "all" ) ) + // Keyword spacing + .map( ( item ) => { + return item.reReplacenocase( + "(\s)*(#keywords.toList( "|" )#)(\s)+", + "#variables.NEW_LINE#\2#variables.NEW_LINE##indent#", + "all" + ) + } ) + // Indented keyword spacing + .map( ( item ) => { + return item.reReplacenocase( + "(#indentedKeywords.toList( "|" )#)", + "#variables.NEW_LINE##indent#\1", + "all" + ) + } ) + .toList( variables.NEW_LINE ); + } + + /** + * Format an incoming json string to a pretty version + * + * @target The target json to prettify + * + * @return The prettified json + */ + string function prettyJson( string target = "" ){ + var padding = 0; + return arguments.target + .reReplace( + "([\{|\}|\[|\]|\(|\)|,])", + "\1#variables.NEW_LINE#", + "all" + ) + .reReplace( + "(\]|\})#variables.NEW_LINE#", + "#variables.NEW_LINE#\1", + "all" + ) + .listToArray( variables.NEW_LINE ) + .map( ( token ) => { + if ( token.reFind( "[\}|\)|\]]" ) && padding > 0 ) { + padding--; + }; + var newToken = repeatString( variables.TAB, padding ) & token.trim(); + if ( token.reFind( "[\{|\(|\[]" ) ) { + padding++; + }; + return newToken; + } ) + .toList( variables.NEW_LINE ); + } + +} diff --git a/models/JVMUtil.cfc b/models/JVMUtil.cfc new file mode 100644 index 0000000..d1cc24a --- /dev/null +++ b/models/JVMUtil.cfc @@ -0,0 +1,53 @@ +component singleton { + + /** + * Get the current request's thread stack + */ + array function getThreadInfo(){ + // Get the ThreadMXBean instance + var threadMXBean = createObject( "java", "java.lang.management.ManagementFactory" ).getThreadMXBean(); + // Set the option to include locked monitors and synchronizers + threadMXBean.setThreadContentionMonitoringEnabled( true ); + // Get the thread information for each thread ID + var threadInfo = []; + return threadInfo.append( + threadMXBean.getThreadInfo( + threadMXBean.getAllThreadIds(), + createObject( "java", "java.lang.Integer" ).MAX_VALUE + ), + true + ); + } + + /** + * Generate a heap dump and store it at the given directory path + * The generated heap dump will be named with the following pattern:
cbdebugger-heapdump-mmm-dd-yyyy_HHnnss_l.hprof+ * + * @directoryPath The directory path to store the heap dump, must be absolute. Defaults to the temporary directory + * + * @return The absolute path to the generated heap dump + */ + string function generateHeapDump( directoryPath ){ + // Create it if it doesn't exist + if ( !directoryExists( arguments.directoryPath = getTempDirectory() ) ) { + directoryCreate( arguments.directoryPath ); + } + + // Get the HotSpotDiagnosticMXBean instance + var ManagementFactory = createObject( "java", "java.lang.management.ManagementFactory" ); + var HotSpotDiagnosticMXBeanClass = createObject( "java", "com.sun.management.HotSpotDiagnosticMXBean" ).getClass(); + var mBeanServer = ManagementFactory.getPlatformMBeanServer(); + var dumpFilePath = arguments.directoryPath & "/cbdebugger-heapdump-#dateTimeFormat( now(), "mmm-dd-yyyy_HHnnss_l" )#.hprof"; + + ManagementFactory + .newPlatformMXBeanProxy( + mBeanServer, + "com.sun.management:type=HotSpotDiagnostic", + HotSpotDiagnosticMXBeanClass + ) + .dumpHeap( dumpFilePath, javacast( "boolean", true ) ); + + return dumpFilePath; + } + +} diff --git a/models/Timer.cfc b/models/Timer.cfc index fa77475..b09ed80 100755 --- a/models/Timer.cfc +++ b/models/Timer.cfc @@ -18,6 +18,44 @@ component accessors="true" singleton threadsafe { return this; } + /** + * Add a timer to the stack manually. You will need the label, executionTime and stoppedAt timestamps + * + * @label The label to use as a timer label + * @executionTime The execution time in ms to register + * @startedAt The date time the timer was started + * @stoppedAt The date time the timer was stopped + * @metadata A struct of metadata to store in the execution timer + * @parent An optional parent label + * @type The type of execution timed: request, view-render, layout-render, event, renderer + */ + function add( + required label, + required executionTime, + startedAt = now(), + stoppedat = now(), + struct metadata = {}, + parent = "", + type = "timer" + ){ + getTimers().insert( + arguments.label, + { + "id" : variables.debuggerService.randomUUID(), + "startedAt" : arguments.startedAt, + "startCount" : getTickCount(), + "method" : arguments.label, + "stoppedAt" : arguments.stoppedAt, + "executionTime" : arguments.executionTime, + "metadata" : arguments.metadata, + "parent" : arguments.parent, + "type" : arguments.type, + "times" : 1 + }, + true + ); + } + /** * Start a timer with a tracking label * diff --git a/models/TimerDelegate.cfc b/models/TimerDelegate.cfc index fec6352..bd30a65 100644 --- a/models/TimerDelegate.cfc +++ b/models/TimerDelegate.cfc @@ -44,4 +44,27 @@ component accessors="true" singleton threadsafe { return variables.timer.timeIt( argumentCollection = arguments ); } + /** + * Add a timer to the stack manually. You will need the label, executionTime and stoppedAt timestamps + * + * @label The label to use as a timer label + * @executionTime The execution time in ms to register + * @startedAt The date time the timer was started + * @stoppedAt The date time the timer was stopped + * @metadata A struct of metadata to store in the execution timer + * @parent An optional parent label + * @type The type of execution timed: request, view-render, layout-render, event, renderer + */ + function addCBTimer( + required label, + required executionTime, + startedAt = now(), + stoppedat = now(), + struct metadata = {}, + parent = "", + type = "timer" + ){ + return variables.timer.add( argumentCollection = arguments ); + } + } diff --git a/package-lock.json b/package-lock.json index e988965..443081a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,12 +40,13 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "dev": true, "dependencies": { - "@babel/highlight": "^7.16.7" + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" @@ -118,13 +119,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.2.tgz", - "integrity": "sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", "dev": true, "dependencies": { - "@babel/types": "^7.18.2", - "@jridgewell/gen-mapping": "^0.3.0", + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" }, "engines": { @@ -245,9 +247,9 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz", - "integrity": "sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true, "engines": { "node": ">=6.9.0" @@ -266,25 +268,25 @@ } }, "node_modules/@babel/helper-function-name": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", - "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "dependencies": { - "@babel/template": "^7.16.7", - "@babel/types": "^7.17.0" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", - "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -409,21 +411,30 @@ } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", - "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true, "engines": { "node": ">=6.9.0" @@ -468,13 +479,13 @@ } }, "node_modules/@babel/highlight": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.12.tgz", - "integrity": "sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "engines": { @@ -482,9 +493,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.18.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.5.tgz", - "integrity": "sha512-YZWVaglMiplo7v8f1oMQ5ZPQr0vn7HPeZXxXWsxXJRjGVrzUFn9OxFQl1sb5wzfootjA/yChhW84BV+383FSOw==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -1591,33 +1602,33 @@ } }, "node_modules/@babel/template": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", - "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.18.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.5.tgz", - "integrity": "sha512-aKXj1KT66sBj0vVzk6rEeAO6Z9aiiQ68wfDgge3nHhA/my6xMM/7HGQUNumKZaoa2qUPQ5whJG9aAifsxUKfLA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.18.2", - "@babel/helper-environment-visitor": "^7.18.2", - "@babel/helper-function-name": "^7.17.9", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.18.5", - "@babel/types": "^7.18.4", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -1626,12 +1637,13 @@ } }, "node_modules/@babel/types": { - "version": "7.18.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.4.tgz", - "integrity": "sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, "engines": { @@ -1716,9 +1728,9 @@ } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.8.tgz", - "integrity": "sha512-YK5G9LaddzGbcucK4c8h5tWFmMPBvRZ/uyWmN1/SbBdIvqGUdWGkJ5BAaccgs6XbzVLsqbPJrBSFwKv3kT9i7w==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", "dev": true, "engines": { "node": ">=6.0.0" @@ -1764,13 +1776,13 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", - "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/@nodelib/fs.scandir": { @@ -3317,9 +3329,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz", - "integrity": "sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow==", + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", + "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", "dev": true, "peer": true, "dependencies": { @@ -4577,9 +4589,9 @@ "dev": true }, "node_modules/json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "bin": { "json5": "lib/cli.js" @@ -4875,10 +4887,16 @@ "dev": true }, "node_modules/nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -5198,9 +5216,9 @@ } }, "node_modules/postcss": { - "version": "8.4.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", - "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "dev": true, "funding": [ { @@ -5210,10 +5228,14 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -6758,9 +6780,9 @@ } }, "node_modules/webpack": { - "version": "5.73.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.73.0.tgz", - "integrity": "sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA==", + "version": "5.76.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.1.tgz", + "integrity": "sha512-4+YIK4Abzv8172/SGqObnUjaIHjLEuUasz9EwQj/9xmPPkYJy2Mh03Q/lJfSD3YLzbxy5FeTq5Uw0323Oh6SJQ==", "dev": true, "peer": true, "dependencies": { @@ -6769,11 +6791,11 @@ "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/wasm-edit": "1.11.1", "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.4.1", + "acorn": "^8.7.1", "acorn-import-assertions": "^1.7.6", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.9.3", + "enhanced-resolve": "^5.10.0", "es-module-lexer": "^0.9.0", "eslint-scope": "5.1.1", "events": "^3.2.0", @@ -6786,7 +6808,7 @@ "schema-utils": "^3.1.0", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.3.1", + "watchpack": "^2.4.0", "webpack-sources": "^3.2.3" }, "bin": { @@ -7034,9 +7056,9 @@ "dev": true }, "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", + "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", "dev": true, "engines": { "node": ">=0.10.0" @@ -7081,12 +7103,13 @@ } }, "@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "dev": true, "requires": { - "@babel/highlight": "^7.16.7" + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" } }, "@babel/compat-data": { @@ -7138,13 +7161,14 @@ } }, "@babel/generator": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.2.tgz", - "integrity": "sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", "dev": true, "requires": { - "@babel/types": "^7.18.2", - "@jridgewell/gen-mapping": "^0.3.0", + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" }, "dependencies": { @@ -7234,9 +7258,9 @@ } }, "@babel/helper-environment-visitor": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz", - "integrity": "sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true }, "@babel/helper-explode-assignable-expression": { @@ -7249,22 +7273,22 @@ } }, "@babel/helper-function-name": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", - "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "requires": { - "@babel/template": "^7.16.7", - "@babel/types": "^7.17.0" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" } }, "@babel/helper-hoist-variables": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", - "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, "requires": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.22.5" } }, "@babel/helper-member-expression-to-functions": { @@ -7359,18 +7383,24 @@ } }, "@babel/helper-split-export-declaration": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", - "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, "requires": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.22.5" } }, + "@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "dev": true + }, "@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true }, "@babel/helper-validator-option": { @@ -7403,20 +7433,20 @@ } }, "@babel/highlight": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.12.tgz", - "integrity": "sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" } }, "@babel/parser": { - "version": "7.18.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.5.tgz", - "integrity": "sha512-YZWVaglMiplo7v8f1oMQ5ZPQr0vn7HPeZXxXWsxXJRjGVrzUFn9OxFQl1sb5wzfootjA/yChhW84BV+383FSOw==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", "dev": true }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { @@ -8154,41 +8184,42 @@ } }, "@babel/template": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", - "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "dev": true, "requires": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" } }, "@babel/traverse": { - "version": "7.18.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.5.tgz", - "integrity": "sha512-aKXj1KT66sBj0vVzk6rEeAO6Z9aiiQ68wfDgge3nHhA/my6xMM/7HGQUNumKZaoa2qUPQ5whJG9aAifsxUKfLA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.18.2", - "@babel/helper-environment-visitor": "^7.18.2", - "@babel/helper-function-name": "^7.17.9", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.18.5", - "@babel/types": "^7.18.4", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.18.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.4.tgz", - "integrity": "sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.16.7", + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" } }, @@ -8254,9 +8285,9 @@ } }, "@jridgewell/resolve-uri": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.8.tgz", - "integrity": "sha512-YK5G9LaddzGbcucK4c8h5tWFmMPBvRZ/uyWmN1/SbBdIvqGUdWGkJ5BAaccgs6XbzVLsqbPJrBSFwKv3kT9i7w==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", "dev": true }, "@jridgewell/set-array": { @@ -8295,13 +8326,13 @@ "dev": true }, "@jridgewell/trace-mapping": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", - "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", "dev": true, "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "@nodelib/fs.scandir": { @@ -9488,9 +9519,9 @@ "dev": true }, "enhanced-resolve": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz", - "integrity": "sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow==", + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", + "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", "dev": true, "peer": true, "requires": { @@ -10429,9 +10460,9 @@ "dev": true }, "json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true }, "kind-of": { @@ -10654,9 +10685,9 @@ "dev": true }, "nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", "dev": true }, "natural-compare": { @@ -10887,12 +10918,12 @@ } }, "postcss": { - "version": "8.4.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", - "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "dev": true, "requires": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } @@ -11933,9 +11964,9 @@ } }, "webpack": { - "version": "5.73.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.73.0.tgz", - "integrity": "sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA==", + "version": "5.76.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.1.tgz", + "integrity": "sha512-4+YIK4Abzv8172/SGqObnUjaIHjLEuUasz9EwQj/9xmPPkYJy2Mh03Q/lJfSD3YLzbxy5FeTq5Uw0323Oh6SJQ==", "dev": true, "peer": true, "requires": { @@ -11944,11 +11975,11 @@ "@webassemblyjs/ast": "1.11.1", "@webassemblyjs/wasm-edit": "1.11.1", "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.4.1", + "acorn": "^8.7.1", "acorn-import-assertions": "^1.7.6", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.9.3", + "enhanced-resolve": "^5.10.0", "es-module-lexer": "^0.9.0", "eslint-scope": "5.1.1", "events": "^3.2.0", @@ -11961,7 +11992,7 @@ "schema-utils": "^3.1.0", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.3.1", + "watchpack": "^2.4.0", "webpack-sources": "^3.2.3" }, "dependencies": { @@ -12124,9 +12155,9 @@ "dev": true }, "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", + "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", "dev": true }, "wrappy": { diff --git a/readme.md b/readme.md index 4253624..1a0d09d 100644 --- a/readme.md +++ b/readme.md @@ -4,9 +4,6 @@
- - - @@ -38,21 +35,21 @@ Request Tracker Collapsed The ColdBox debugger is a light-weigth performance monitor and profiler for your ColdBox applications. It tracks your requests, whether Ajax, traditional or REST, it's environment, execution and much more. Here is a listing of some of the capabilities you get with the ColdBox Debugger: -- Track all incoming requests to your applications in memory or offloaded cache +- Track all incoming requests to your applications - Track exceptions and execution environment -- Track incoming http requests, parameters, body and much more +- Track incoming HTTP requests, parameters, body, and much more - Track final request collections -- Track Hibernate and `cborm` queries, criteria queries and session stats -- Track `qb` and `quick` queries, entities and stats -- Tap into LogBox via our Tracer messages and discover logging on a per request basis -- Profile execution and results of **ANY** model object -- Profile execution of **ANY** ColdBox interception point +- Track Hibernate and cborm queries, criteria queries, and session stats +- Track qb and quick queries, entities, and stats +- Tap into LogBox via our Tracer messages and discover logging on a per-request basis +- Profile execution and results of ANY model object +- Profile execution of ANY ColdBox interception point - Custom Timer helpers for adding timing methods and annotations anywhere in your code - Profile your production or development apps with ease - Track ColdBox modules and lifecycles -- Highly configurable -- Highly extensible +- Track Hyper HTTP/S calls - Track Adobe ColdFusion Queries (ColdFusion 2018+) +- Track Lucee Queries ## License @@ -60,6 +57,7 @@ Apache License, Version 2.0. ## Important Links +- Docs: https://cbdebugger.ortusbooks.com/ - Source: https://github.com/coldbox-modules/cbdebugger - ForgeBox: https://www.forgebox.io/view/cbdebugger - Community: https://community.ortussolutions.com/c/box-modules/cbdebugger/38 @@ -74,488 +72,22 @@ Apache License, Version 2.0. ## Optional Requirements -### cborm Collector - -- Hibernate extension (on Lucee) -- `orm` package on ACF 2021 - -### Adobe SQL Collector - -- `cbdebugger` package on ACF 2021 - - Check `Database Activity` on the debugger page or cfconfig setting (`debuggingShowDatabase : true`) +https://cbdebugger.ortusbooks.com/essentials/installation#optional-requirements # Instructions -Just drop into your **modules** folder or use CommandBox to install - -`box install cbdebugger` - -This will activate the debugger in your application and render out at the end of a request or by visiting the debugger request tracker visualizer at `/cbdebugger`. +https://cbdebugger.ortusbooks.com/essentials/installation ## Settings The debugger is highly configurable and we have tons of settings to assist you in your development adventures and also in your performance tuning. Please note that the more collectors you activate, the **slower** your application can become. By default we have pre-selected defaults which add neglible performance to your applications. -Open your `config/coldbox.cfc` configuration object and add into the `moduleSettings` the `cbDebugger` key with the following options: - -```js -moduleSettings = { - // Debugger Settings - cbDebugger = { - // Master switch to enable/disable request tracking into storage facilities. - enabled : true, - // Turn the debugger UI on/off by default. You can always enable it via the URL using your debug password - // Please note that this is not the same as the master switch above - // The debug mode can be false and the debugger will still collect request tracking - debugMode : true, - // The URL password to use to activate it on demand - debugPassword : "cb:null", - // This flag enables/disables the end of request debugger panel docked to the bottom of the page. - // If you disable it, then the only way to visualize the debugger is via the `/cbdebugger` endpoint - requestPanelDock : true, - // Request Tracker Options - requestTracker : { - // Track all cbdebugger events, by default this is off, turn on, when actually profiling yourself :) How Meta! - trackDebuggerEvents : false, - // Store the request profilers in heap memory or in cachebox, default is memory. Options are: memory, cachebox - storage : "memory", - // Which cache region to store the profilers in if storage == cachebox - cacheName : "template", - // Expand by default the tracker panel or not - expanded : true, - // Slow request threshold in milliseconds, if execution time is above it, we mark those transactions as red - slowExecutionThreshold : 1000, - // How many tracking profilers to keep in stack: Default is to monitor the last 20 requests - maxProfilers : 50, - // If enabled, the debugger will monitor the creation time of CFC objects via WireBox - profileWireBoxObjectCreation : false, - // Profile model objects annotated with the `profile` annotation - profileObjects : false, - // If enabled, will trace the results of any methods that are being profiled - traceObjectResults : false, - // Profile Custom or Core interception points - profileInterceptions : false, - // By default all interception events are excluded, you must include what you want to profile - includedInterceptions : [], - // Control the execution timers - executionTimers : { - expanded : true, - // Slow transaction timers in milliseconds, if execution time of the timer is above it, we mark it - slowTimerThreshold : 250 - }, - // Control the coldbox info reporting - coldboxInfo : { expanded : false }, - // Control the http request reporting - httpRequest : { - expanded : false, - // If enabled, we will profile HTTP Body content, disabled by default as it contains lots of data - profileHTTPBody : false - } - }, - // ColdBox Tracer Appender Messages - tracers : { enabled : true, expanded : false }, - // Request Collections Reporting - collections : { - // Enable tracking - enabled : false, - // Expanded panel or not - expanded : false, - // How many rows to dump for object collections - maxQueryRows : 50, - // Max number to use when dumping objects via the top argument - maxDumpTop: 5 - }, - // CacheBox Reporting - cachebox : { enabled : false, expanded : false }, - // Modules Reporting - modules : { enabled : false, expanded : false }, - // Quick and QB Reporting - qb : { - enabled : true, - expanded : false, - // Log the binding parameters - logParams : true - }, - // cborm Reporting - cborm : { - enabled : false, - expanded : false, - // Log the binding parameters (requires CBORM 3.2.0+) - logParams : true - }, - // Adobe ColdFusion SQL Collector - acfSql : { - enabled : true, - expanded : false, - // Log the binding parameters - logParams : true - }, - // Async Manager Reporting - async : { - enabled : true, - expanded : false - } - } -} -``` - -## WireBox Mappings - -The module will also register the following model objects for you: - -- `debuggerService@cbdebugger` -- `timer@cbdebugger` - -The `DebuggerService` can be used a-la-carte for your debugging purposes. - -The `Timer` object will allow you to time code execution and send the results to the debugger panel. - -## Helper Mixins - -This module will also register a few methods in all your handlers/interceptors/layouts and views. You can use them for turning the debugger panel on/off, timing code execution and much more. - -```js - /** - * Method to turn on the rendering of the debug panel on a request - */ - any function showDebugger() - - /** - * Method to turn off the rendering of the debug panel on a request - */ - any function hideDebugger() - - /** - * See if the debugger will be rendering or not - */ - boolean function isDebuggerRendering() - - /** - * Start a timer with a tracking label - * - * @label The tracking label to register - * - * @return A unique tracking hash you must use to stop the timer - */ - function startCBTimer( required label ) - - /** - * End a code timer with a tracking hash. If the tracking hash is not tracked we ignore it - * - * @labelHash The timer label hash to stop - */ - function stopCBTimer( required labelHash ) - - /** - * Time the execution of the passed closure that we will execution for you - * - * @label The label to use as a timer label - * @closure The target to execute and time - */ - function cbTimeIt( required label, required closure ) - - /** - * Shortcut to get a reference to the ColdBox Debugger Service - */ - function getCBDebugger() - - /** - * Push a new tracer into the debugger. This comes from LogBox, so we follow - * the same patterns - * - * @message The message to trace - * @severity The severity of the message - * @category The tracking category the message came from - * @timestamp The timestamp of the message - * @extraInfo Extra info to store in the tracer - */ - DebuggerService function cbTracer( - required message, - severity = "info", - category = "", - timestamp = now(), - extraInfo = "" - ) -``` - -## Timer Delegate - -We have included a ColdBox 7 Timer delegate: `TimerDelegate@cbDebguger` that can add timing capabilities to any CFC - -```js -component delegates="TimerDelegate@cbDebguger"{ - -... - startCBTimer(); - stopCBTimer(); - timeIt(); -... - -} - -``` - -## Debugger Events - -The debugger also announces several events that you can listen to and extend the debugging and profiling capabilities: - -```js -// Before the debugger panel is rendered -"beforeDebuggerPanel", -// After the last debugger panel is rendered -"afterDebuggerPanel", -// Before any individual profiler report panels are rendered -"beforeProfilerReportPanels", -// After any individual profiler report panels are rendered -"afterProfilerReportPanels", -// When the request tracker has been created and placed in request scope -"onDebuggerRequestTrackerCreation", -// Before the request tracker is saved in the profiler, last chance to influence the recording -"onDebuggerProfilerRecording" -``` - -## Profiling Objects - -The ColdBox debugger allows you to profile the execution of ANY method in ANY CFC via our AOP pointcuts. All you need to do is add the `profile` annotation to a method or component declaration in your model/orm objects. Once you do, the debugger will track the execution of those methods in the debug timers panel for you. First thing to do is make sure the setting is turned on: - -```js -requestTracker : { - // Profile model objects annotated with the `profile` annotation - profileObjects : true, - // If enabled, will trace the results of any methods that are being profiled - traceObjectResults : false, -} -``` - -The `traceObjectResults` if `true` will track the actual results of the method calls into your debugger timer panel. Careful, as we will serialize anything you send to us. Then add the `profile` annotation to any method or cfc. - -```js -/** - * Profile all methods in this component - */ -component profile{ - -} - -// Add the profile to this method to track it -function saveAllObjects() profile{ - -} -``` - -Profiling objects is great because you can just annotate and forget. Nothing to turn off in production. - -## WireBox Object Creation Profiling - -There will be cases where you need to test the performance of the creation of certain objects in WireBox. You can do so by activating the `profileWireBoxObjectCreation` setting in the `requestTracker`. Once enabled, you will see the profiling of all objects created by WireBox in the debug timers. - -## Profiling Interceptions - -
- -
- --Debug Timers -
- -In an event-driven framework like ColdBox, there are tons of events that fire within traditional request/response transactions. You can activate our tracker and we will trace and profile interception calls. Activate it via the settings first: - -```js -// Profile Custom or Core interception points -profileInterceptions : true, -// By default all interception events are excluded, you must include what you want to profile -includedInterceptions : [ "onUserSave", "ORMPostLoad" ], -``` - -Once activated, you can add a collection of interception points to profile in your application. We will track them for you and even if they are ORM calls we will tell you which entity initiated the call. - -## HTTP Request Tracking - -- -
-- HTTP Visualizer -
- -The debugger will track all incoming http calls into your application. It will show you all the relevant method, query string, form params, headers, and even the HTTP Body (if enabled). By default, the HTTP Body is ignored as it can be big and tracking it on every request can reduce performance. However, you can easily turn it on and inspect the incoming packets. - -```js -requestTracker = { - // Control the http request reporting - httpRequest : { - expanded : false, - // If enabled, we will profile HTTP Body content, disabled by default as it contains lots of data - profileHTTPBody : true - } -} -``` - -## ColdBox Tracers - -- -
- -- ColdBox Tracers -
- -The debugger also ships with a LogBox appender we call the ColdBox Tracer. This tracer will absorb the usage of log `info(), fatal(), error(), warn(), debug()` calls within your application and group them to the request that they initiated from. You can then visualize and inspect them in your debugger. All you have to do is activate it and enjoy! - -```js -// ColdBox Tracer Appender Messages -tracers : { enabled : true, expanded : false }, -``` - -Please note that by default the tracer appender will log any logging level from `fatal` to `debug` to your request tracker and will track anything sent to it. So also note that this can have an impact on performance if you are sending tons of complex objects to the `extraInfo` argument. With much power, comes much responsibility! - -## Hibernate + cborm - -- -
-- Grouped cborm calls -
- -We have a dedicated panel in the debugger that will track all criteria queries and `executeQuery()` calls from within your application. It will show you a grouped or a timeline visualizer of all these sql calls. All you have to do is activate it: - -```js -// cborm Reporting -cborm : { - enabled : true, - expanded : false, - // Log the binding parameters (requires CBORM 3.2.0+) - logParams : true -} -``` - -You can also enable `logParams` and we will track the original executable parameters of the query so you can debug the actual values of these executions. We will also track from WHERE in the application the sql execution came from and you can even open the file to that specific line number using our code editor integrations by clicking our **open in editor** buttons. - -> **Note**: CBDebugger's `cborm.logParams` setting requires CBORM 3.2.0 or higher. - -The grouped view you see above will give you an aggregate look of all the sql calls made during the request and their frequency of execution. It will also give you a mini report of those specific sql groups with data about where the query originated from in your source code and the binding parameters, if activated. - -- -
-- Timeline cborm calls -
- -The timeline view gives you a track of all the sql requests made via cborm from start to finish in your request. - -## qb/Quick - -- -
-- qb/quick calls -
- -We have also created a `qb` and `quick` panel which will track all SQL calls made via `qb` or via `quick` during your request. We offer the same grouped or timeline visualizer for all these sql calls and even the capability to track from where the calls where made from and open them in your favorite editor to the line number. All you have to do is activate it: - -```js -// Quick and QB Reporting -qb : { - enabled : true, - expanded : false, - // Log the binding parameters - logParams : true -}, -``` - -Also remember that you can activate the binding parameters to the sql calls. - -## Adobe ColdFusion SQL Tracking - -We have also created an `ACF Sql` panel which will track all SQL calls made during your request. We offer the same grouped or timeline visualizer for all these sql calls and even the capability to track from where the calls where made from and open them in your favorite editor to the line number. All you have to do is activate it: - -```js -// Adobe ColdFusion SQL Collector -acfSql : { - enabled : true, - expanded : false, - logParams : true -}, -``` -**Note:** This feature works with `ColdFusion 2018+` and requires the `Database Activity` box to be checked in the ACF `Debugging & Logging` page. If using ColdFusion 2021, you will need the `CF debugger` module installed as well. You can use the ACF CLI package manager, or the CommandBox command of `cfpm install debugger`. If it is not installed, install it and then restart the server before using this module. - -## Modules Panel - -- -
-- Modules Tracker -
- -If enabled, we will track also the loaded modules in your application: - -```js -// Modules Reporting -modules : { enabled : true, expanded : false }, -``` - -From the panel you will be able to analyze the registration and activation of all your application modules. You can even reload, unload and execute life-cycle commands against them. - -## CacheBox Monitor - -- -
-- CacheBox Monitor -
- -You can also enable the CacheBox monitor and get complete insight into all your registered application caches. - -```js -// CacheBox Reporting -cachebox : { enabled : true, expanded : false }, -``` - -## Debugger Visualizer - -- -
-- Debugger Visualizer -
- -A part from debugging the incoming request and presenting the debugger at the end of the request, you can also navigate to `/cbdebugger` and visualize the Debugger request tracker. This panel will monitor ALL incoming requests to your application: rest, soap, ajax, etc. - -You can execute several commands from this visualizer: - -- Clear all request history -- Reinit ColdBox -- Shutdown the debugger visualizer -- Refresh the requests -- Auto refresh the requests - -You can then select a specific request and open the request report with all the tracked information. - -Please note that the request tracker in the debugger has a configurable capacity for requests. By default we track the last 25 requests into the application. You can either increase it or reduce it to your hearts content. Just note that the more you track, the more memory it consumes unless you offload it to an external cache. - -```js -// How many tracking profilers to keep in stack: Default is to monitor the last 20 requests -maxProfilers : 25, -``` - -## Storing Profilers Off-Heap - -You can tell the debugger to store the profilers and instrumentation data off-heap by using the `storage` setting and connecting it to a distributed cache like Redis, Couchbase, Mongo, Elastic, etc. All you need to do is change the `storage` to `cachebox` and update the `cacheName` to point to the distributed cache name you have configured in your `config/Cachebox.cfc`. +You can find how to configure the debugger here: +https://cbdebugger.ortusbooks.com/essentials/configuration -```js -storage : "cachebox", -cacheName : "couchbase" -``` +## Usage -With that configuration, all the profiler data and instrumentation will be sent to the distributed cache. +https://cbdebugger.ortusbooks.com/essentials/request-tracker ******************************************************************************** Copyright Since 2005 ColdBox Framework by Luis Majano and Ortus Solutions, Corp diff --git a/resources/assets/images/CBDebugger-logo.png b/resources/assets/images/CBDebugger-logo.png new file mode 100644 index 0000000..f01ed20 Binary files /dev/null and b/resources/assets/images/CBDebugger-logo.png differ diff --git a/resources/assets/images/CBDebugger-logo.svg b/resources/assets/images/CBDebugger-logo.svg new file mode 100644 index 0000000..19f32f0 --- /dev/null +++ b/resources/assets/images/CBDebugger-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/assets/sass/cbdebugger.scss b/resources/assets/sass/cbdebugger.scss index 4b3282b..0418f04 100644 --- a/resources/assets/sass/cbdebugger.scss +++ b/resources/assets/sass/cbdebugger.scss @@ -1,4 +1,17 @@ [x-cloak] { display: none !important; } +.cbd-dock{ + position: fixed; + bottom: 0; + left: 0; + width: 100%; + overflow-y: auto; + max-height: 100%; + z-index: 1000; + + .cbd-contentView{ + border-radius: 0px !important; + } +} .cbd-debugger{ font-family: Verdana,Arial,sans-serif; font-size: 11px; @@ -160,8 +173,6 @@ background: #327A9F; padding:5px 5px; cursor: pointer; - margin-bottom: 2px; - border-radius: 5px; &:hover{ background: #D7EBF9; diff --git a/server-adobe@2023.json b/server-adobe@2023.json new file mode 100644 index 0000000..f051571 --- /dev/null +++ b/server-adobe@2023.json @@ -0,0 +1,29 @@ +{ + "name":"cbdebugger-adobe@2023", + "app":{ + "serverHomeDirectory":".engine/adobe2023", + "cfengine":"adobe@2023" + }, + "web":{ + "http":{ + "port":"60299" + }, + "rewrites":{ + "enable":"true" + }, + "webroot": "test-harness", + "aliases":{ + "/moduleroot/cbdebugger":"../" + } + }, + "jvm":{ + "heapSize":"1024" + }, + "openBrowser":"false", + "cfconfig": { + "file" : ".cfconfig.json" + }, + "scripts" : { + "onServerInstall":"cfpm install zip,orm,mysql,postgresql,sqlserver,feed,chart,debugger" + } +} diff --git a/server-lucee@5.json b/server-lucee@5.json index 752d969..59eefe2 100644 --- a/server-lucee@5.json +++ b/server-lucee@5.json @@ -19,5 +19,8 @@ "openBrowser":"false", "cfconfig":{ "file":".cfconfig.json" + }, + "env":{ + "lucee-extensions":"D062D72F-F8A2-46F0-8CBC91325B2F067B" } } diff --git a/test-harness/.DS_Store b/test-harness/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/test-harness/.DS_Store differ diff --git a/test-harness/box.json b/test-harness/box.json index 4de8f82..bf9f0bf 100644 --- a/test-harness/box.json +++ b/test-harness/box.json @@ -5,9 +5,12 @@ "private":true, "description":"", "dependencies":{ - "coldbox":"be", + "coldbox":"^7.0.0", "quick":"^4.2.4", - "cborm":"^4.0.0" + "cborm":"^4.0.0", + "cbmailservices":"^2.7.1+112", + "hyper":"^7.1.0", + "mockdatacfc":"^3.6.0+13" }, "devDependencies":{ "testbox":"*" @@ -16,6 +19,9 @@ "coldbox":"coldbox/", "testbox":"testbox/", "quick":"modules/quick/", - "cborm":"modules/cborm/" + "cborm":"modules/cborm/", + "cbmailservices":"modules/cbmailservices/", + "hyper":"modules/hyper/", + "mockdatacfc":"modules/mockdatacfc/" } } diff --git a/test-harness/config/Coldbox.cfc b/test-harness/config/Coldbox.cfc index 6935b8b..27798b8 100644 --- a/test-harness/config/Coldbox.cfc +++ b/test-harness/config/Coldbox.cfc @@ -80,13 +80,13 @@ cacheName : "template", trackDebuggerEvents : false, // Expand by default the tracker panel or not - expanded : true, + expanded : false, // Slow request threshold in milliseconds, if execution time is above it, we mark those transactions as red slowExecutionThreshold : 1000, // How many tracking profilers to keep in stack: Default is to monitor the last 20 requests maxProfilers : 25, // If enabled, the debugger will monitor the creation time of CFC objects via WireBox - profileWireBoxObjectCreation : false, + profileWireBoxObjectCreation : true, // Profile model objects annotated with the `profile` annotation profileObjects : true, // If enabled, will trace the results of any methods that are being profiled @@ -94,7 +94,7 @@ // Profile Custom or Core interception points profileInterceptions : true, // By default all interception events are excluded, you must include what you want to profile - includedInterceptions : [ "ORMPostLoad", "ORMPostNew" ], + includedInterceptions : [ "ORMPostNew" ], // Control the execution timers executionTimers : { expanded : true, @@ -147,7 +147,10 @@ enabled : true, expanded : false, logParams : true - } + }, + luceeSQL : { enabled : true, expanded : false, logParams : true }, + // Hyper Collector + hyper : { enabled : true, expanded : false, logRequestBody : true, logResponseData : true } } }; diff --git a/test-harness/handlers/Api.cfc b/test-harness/handlers/Api.cfc new file mode 100644 index 0000000..99a9889 --- /dev/null +++ b/test-harness/handlers/Api.cfc @@ -0,0 +1,39 @@ +component extends="coldbox.system.RestHandler"{ + + any function index( event, rc, prc ){ + sleep( randRange(100,2000 ) ); + event.getResponse() + .setData( + getInstance( "MockData@MockDataCFC" ) + .mock( + $num = "rnd:10:20", + name = "name", + id = "uuid", + email = "email", + biography = "lorem", + createdDate = "datetime", + updatedDate = "datetime", + profileUrl = "imageURL" + ) + ); + } + + any function person( event, rc, prc ){ + sleep( randRange(100,2000 ) ); + event.getResponse() + .setData( + getInstance( "MockData@MockDataCFC" ) + .mock( + $returnType = "struct", + name = "name", + id = "uuid", + email = "email", + biography = "lorem", + createdDate = "datetime", + updatedDate = "datetime", + profileUrl = "imageURL" + ) + ); + } + +} diff --git a/test-harness/handlers/Main.cfc b/test-harness/handlers/Main.cfc index b4578fb..17a551e 100644 --- a/test-harness/handlers/Main.cfc +++ b/test-harness/handlers/Main.cfc @@ -6,6 +6,7 @@ component { property name="qb" inject="queryBuilder@qb"; property name="roleService" inject="entityService:Role"; property name="userService" inject="entityService:User"; + property name="hyper" inject="HyperBuilder@hyper"; /** @@ -98,6 +99,56 @@ component { event.renderData( data = "+ Use the links below to generate debugging data +
+#sqlFormatter.format( - args.profiler.cfQueries.grouped[ sqlHash ].sql - )#+
#withoutDumbWhitespace#@@ -230,7 +228,7 @@ >
#jsonFormatter.formatJSON( json : q.attributes, spaceAfterColon : true )#+
#formatter.prettyJson( json : q.attributes, spaceAfterColon : true )#@@ -256,8 +254,7 @@ args : { sqlData : args.profiler.cfQueries.all, debuggerService : args.debuggerService, - sqlFormatter : sqlFormatter, - jsonFormatter : jsonFormatter, + formatter : formatter, appPath : appPath }, prePostExempt : true @@ -279,8 +276,7 @@ return executionTimeA < executionTimeB ? 1 : -1; } ), debuggerService : args.debuggerService, - sqlFormatter : sqlFormatter, - jsonFormatter : jsonFormatter, + formatter : formatter, appPath : appPath }, prePostExempt : true diff --git a/views/main/panels/requestTracker/acfSqlTable.cfm b/views/main/panels/requestTracker/acfSqlTable.cfm index b383857..c7178e1 100644 --- a/views/main/panels/requestTracker/acfSqlTable.cfm +++ b/views/main/panels/requestTracker/acfSqlTable.cfm @@ -78,7 +78,8 @@ >
#args.sqlFormatter.format( q.body )#+
#withoutDumbWhitespace#@@ -100,7 +101,7 @@ >
#args.jsonFormatter.formatJSON( json : q.attributes, spaceAfterColon : true )#+
#args.formatter.prettyJson( json : q.attributes, spaceAfterColon : true )#diff --git a/views/main/panels/requestTracker/cbormPanel.cfm b/views/main/panels/requestTracker/cbormPanel.cfm index 61009fe..5d99cbe 100644 --- a/views/main/panels/requestTracker/cbormPanel.cfm +++ b/views/main/panels/requestTracker/cbormPanel.cfm @@ -2,8 +2,7 @@
#ltrim( - sqlFormatter.format( args.profiler.cborm.grouped[ sqlHash ].sql ) - )#+
#withoutDumbWhitespace#@@ -231,7 +229,7 @@ >
#jsonFormatter.formatJSON( json : q.params, spaceAfterColon : true )#+
#formatter.prettyJson( json : q.params, spaceAfterColon : true )#@@ -258,8 +256,7 @@ args : { sqlData : args.profiler.cborm.all, debuggerService : args.debuggerService, - sqlFormatter : sqlFormatter, - jsonFormatter : jsonFormatter, + formatter : formatter, appPath : appPath }, prePostExempt : true @@ -280,8 +277,7 @@ return a.executionTime < b.executionTime ? 1 : -1; } ), debuggerService : args.debuggerService, - sqlFormatter : sqlFormatter, - jsonFormatter : jsonFormatter, + formatter : formatter, appPath : appPath }, prePostExempt : true diff --git a/views/main/panels/requestTracker/cbormSqlTable.cfm b/views/main/panels/requestTracker/cbormSqlTable.cfm index 182bf09..906e083 100644 --- a/views/main/panels/requestTracker/cbormSqlTable.cfm +++ b/views/main/panels/requestTracker/cbormSqlTable.cfm @@ -71,7 +71,8 @@ >
#args.sqlFormatter.format( q.sql )#+
#withoutDumbWhitespace#@@ -93,7 +94,7 @@ >
#args.jsonFormatter.formatJSON( json : q.params, spaceAfterColon : true )#+
#args.formatter.prettyJson( json : q.params, spaceAfterColon : true )#diff --git a/views/main/panels/requestTracker/coldboxPanel.cfm b/views/main/panels/requestTracker/coldboxPanel.cfm index 40c4bf1..b0e15fe 100644 --- a/views/main/panels/requestTracker/coldboxPanel.cfm +++ b/views/main/panels/requestTracker/coldboxPanel.cfm @@ -2,8 +2,7 @@
#jsonFormatter.formatJSON( args.profiler.requestData.content )#
+ #formatter.prettyJson( args.profiler.requestData.content )#
- #jsonFormatter.formatJSON( args.profiler.formData )#
+ #formatter.prettyJson( args.profiler.formData )#
Count | +Request Information | +||||||||
---|---|---|---|---|---|---|---|---|---|
+
+ #args.profiler.hyper.grouped[ requestHash ].count#
+
+ |
+
+
+
+
+ |
+ ||||||||
+ |
+
|
+
Status | +Timestamp | +Execution Time | +Request | +
---|---|---|---|
+
+
+ |
+
+ + #TimeFormat( thisRequest.timestamp,"hh:MM:SS.l tt" )# + | + ++ #numberFormat( thisRequest.executionTime )# ms + | + +
+
+
+
+
+
+
+ #thisRequest.request.method#>#thisRequest.request.url#
+
+
+
+
+
+ Request: +
+
+
+ Response: +
+
+
+
+
+ Called From:
+
+
+
+
+
+
+
+
+
+ #replaceNoCase( thisRequest.caller.template, args.appPath, "" )#:#thisRequest.caller.line#
+
+
+ |
+
+"debuggingDBEnabled":"true", +"debuggingEnabled":"true", ++
Count | +Query | +||||||||
---|---|---|---|---|---|---|---|---|---|
+
+ #args.profiler.cfQueries.grouped[ sqlHash ].count#
+
+ |
+
+
+
+
+ |
+ ||||||||
+ |
+
|
+
Timestamp | +Execution Time | +Datasource | +Query | +
---|---|---|---|
+ #timeFormat( + args.debuggerService.fromEpoch( q.startTime ), + "hh:MM:SS.l tt" + )# + | + ++ #numberFormat( ( q.executionTime / 1000000 ) )# ms + | + ++ #q.datasource# + | + +
+
+
+ Called From:
+
+
+
+
+
+
+
+
+
+ #q.src#
+
+
+
+
+
+ |
+
#sqlFormatter.format( - args.profiler.qbQueries.grouped[ sqlHash ].sql - )#+
#withoutDumbWhitespace#
#jsonFormatter.formatJSON( json : q.params, spaceAfterColon : true )#+
#formatter.prettyJson( json : q.params, spaceAfterColon : true )#
#args.sqlFormatter.format( q.sql )#+
#withoutDumbWhitespace#@@ -85,7 +86,7 @@ >
#args.jsonFormatter.formatJSON( json : q.params, spaceAfterColon : true )#+
#args.formatter.prettyJson( json : q.params, spaceAfterColon : true )#