Lifecycle Events vs. Contextual Events

Before you continue through this section, you'll need to understand the differences between Mura's lifecycle events and Mura's contextual events.

  • "Lifecycle" events generally get triggered on every page request, and represent the execution of Mura's normal request flow. Mura consists of two unique lifecycles: the Front-end Lifecycle, and the Admin Lifecycle.
  • "Contextual" events aren't triggered on every page request, because they occur in response to the specific event(s) or action(s) that preceded them.

For example, Mura-related events that occur when editing a "User" are only triggered when a user is being created or updated, and would not necessarily be triggered in the course of a normal front-end request.

Note: Contextual events only contain data that is directly supplied to it by the Mura core. If you need to access to the full event scope itself (i.e., during a front-end or admin rendering event), it can be accessed via m.getGlobalEvent().

Mura "event" Scope

When working with events, keep CFML's scopes in mind. As noted in the Mura Scope section, in addition to the CFML scopes, Mura has its own scope called the Mura Scope.

The Mura Scope has a special subscope called the "event" scope, and it is created on every request. It can be referenced via m.event(). If you need to access the global event scope from within a contextual event, you may use m.getGlobalEvent().

Mura's event scope wraps CFML's request, form, and URL scopes. Mura also injects additional data and helper methods into the event scope, and the availability of the data is dependent upon the context in which you may be accessing it. As covered in the Mura Objects section, you may also store your own data in Mura's event scope for use within your own application logic.

Syntax

You can use the following examples to "get" and/or "set" various attributes of Mura's event scope. Use whichever syntax feels best to you.

Getters

m.event('attributeName')
m.event().get('attributeName')
m.event().get{AttributeName}()
m.event().getValue('attributeName')

Setters

m.event('attributeName', 'someValue')
m.event().set('attributeName', 'someValue')
m.event().set{AttributeName}('someValue')
m.event().setValue('attributeName', 'someValue')

Event Hooks

In this section, we'll cover Mura's various event hooks/methods, or trigger points, you can use to either add to, or even replace Mura's business logic and functionality.

One thing you'll want to think of when using this section is determining the point(s) in which you wish to add your logic. For example, are you trying to do something that occurs while the Mura application is loading up? Or, are you attempting to do something during  a normal, front-end request? Are you trying to do something when a content item is being updated? Maybe you're attempting to do something when a session begins. These are all good questions that can point you in the right direction. Once you've determined the answers to these types of questions, you can dig into the available event hooks, register your event handlers, and implement your custom application logic.

Also, when working with Mura events, keep in mind that all events are automatically passed in the Mura (m) scope as an argument. The example below illustrates a sample method with the argument being passed in.

public any function onSomeEvent(m) {
  // do something here
}

To can obtain the event scope via the Mura scope, follow the example below.

public any function onSomeEvent(m) {
  // obtain the `event` scope via the Mura Scope
  var e = arguments.m.event();
}

Keep in mind when working with some contextual events, you may need to access the "global" event scope itself. The example below demonstrates accessing the global event, if necessary.

public any function onSomeEvent(m) {
  // access the global event scope
  var globalEvent = arguments.m.getGlobalEvent();
}

Finally, you may add any of these events to a registered event handler, in order for Mura to execute them. See the Event Handlers section for more information.

Event Prefixes

As you review the available events, you'll notice a common naming convention. Mura's events all start with a prefix, which informs you whether you're replacing Mura's business logic, or adding to Mura's business logic. Keep the following information in mind as you dive into the rest of this section.

  • standard{Event}
    • All "standard" events are points where you can replace Mura's business logic and functionality. These events are all defined within the file located at {context}/core/mura/Handler/standardEventsHandler.cfc
  • on{Event}
    • All "on" events are points where you can add to Mura's business logic and functionality. The important thing to understand about "on" events is that these are not necessarily "defined" anywhere. These types of events are merely "announced" during the normal execution of a request.

Global vs. Site

In addition to the "standard" vs. "on" prefixes, you'll notice many events also have additional common names after the prefix:

  • onGlobal{Event}
    • All "global" events are those that occur throughout the entire instance of Mura, and are not bound to any specific site.
  • onSite{Event}
    • All "site" events occur site-wide, and are bound to the specific site they have been registered to.

Before vs. After

Another common naming convention includes using the words "before" and "after" to indicate whether something is happening immediately before Mura is about to do something, or after Mura has finished doing something.

  • onBefore{Event}
    • All "before" events are announced immediately before Mura is about to execute its normal functionality.
  • onAfter{Event}
    • All "after" events are announced immediately after Mura has executed its normal functionality.

CFML Application Events

As a CFML developer, you should be familiar with using application event handlers. The most commonly used CFML methods are outlined below, with a direct mapping to Mura's methods. Using Mura's methods in your own event handlers allows you to stay on the upgrade path, without having to modify Mura's Application.cfc directly.

CFML Method Analogous Mura Event
onApplicationStart onApplicationLoad
onApplicationEnd Not implemented in Mura at this time
onSessionStart onGlobalSessionStart
onSessionEnd onGlobalSessionEnd
onRequestStart onGlobalRequestStart
onRequest Not implemented in Mura at this time
onRequestEnd onGlobalRequestEnd
onMissingTemplate onGlobalMissingTemplate
onError onGlobalError

 

Standard Events

As previously discussed, events prefixed with "standard" are points where you can replace Mura's business logic and functionality. To view their method definitions, and what they're doing specifically, open the file located under {context}/core/mura/Handler/standardEventsHandler.cfc. You can also view these methods via Mura's Component API at http://www.getmura.com/component-api/7.1/index.html?mura/Handler/standardEventsHandler.html.

There are three primary suffixes for "standard" events:

    • validator
      • Validators inspect the "event" or "request" itself, and forward the request/event to the appropriate handler, if necessary.
    • handler
      • Handlers usually set values in the "global event", or redirect the user somewhere.
    • translator
      • Translators check to see if the requested returnformat is JSON, and if so, utilizes Mura's JSON API to handle the request.
    Method When run
    standard404Handler Called by standard404Validator when the content bean in the current request is new.
    standard404Validator Called by standardSetContentHandler on each request.
    standardDoActionsHandler  
    standardDoResponseHandler  
    standardEnableLockdownHandler  
    standardEnableLockdownValidator  
    standardFileTranslationHandler  
    standardFileTranslator  
    standardForceSSLHandler  
    standardForceSSLValidator  
    standardJSONTranslator  
    standardLinkTranslationHandler  
    standardLinkTranslator  
    standardMobileHandler  
    standardMobileValidator  
    standardPostLogoutHandler  
    standardRequireLoginHandler  
    standardRequireLoginValidator  
    standardSetContentHandler  
    standardSetIsOnDisplayHandler  
    standardSetLocaleHandler  
    standardSetPermissionsHandler  
    standardSetPreviewHandler  
    standardTrackSessionHandler  
    standardTrackSessionValidator  
    standardTranslationHandler  
    standardWrongDomainValidator  
    standardWrongFilenameHandler  
    standardWrongFilenameValidator  

     

    Custom Events

    In addition to all of Mura's event hooks, developers may also create their own, custom event hooks. The main decision you'll want to make is whether you wish to "announce" an event, or "render" an event. Regardless of whether you choose to announce an event, or render an event, Mura will trigger your event as illustrated below, and in turn, any registered event handlers with these methods defined, will be executed:

    on{YourEvent}
    

    Announcing Events

    When you "announce" an event, you're essentially sending a notification throughout Mura that something in particular is about to occur, or has just occurred. You may omit the "on" from your event name when announcing it. However, your method itself should contain the "on" prefix.

    Syntax

    The basic syntax for announcing an event is:

    m.announceEvent('YourEvent', m);
    // OR
    m.announceEvent('onYourEvent', m);
    

    When Mura encounters the code above, it will search for any registered event handlers to locate onYourEvent(), and if found, the method will be executed.

    Example

    The following example illustrates a very simple form, with a text field named myField. The value attribute will be pre-populated with its own value. In other words, since the event scope itself wraps CFML's URL, Form, and Request scopes, we can check the event scope for the value, and if the form is submitted, then any value entered will be used to pre-populate itself.

    <form method="post">
      <input type="text" name="myField" value="[m]esapiEncode('html_attr', m.event('myField'))[/m]">
      <input type="hidden" name="myFormIsSubmitted" value="true">
      <input type="submit">
    </form>

    In the example form above, we're using a hidden field named myFormIsSubmitted with its value set to "true". By checking the event scope for this value, if found, we can trigger an event to occur, as shown the example below.

    // check form submission via `onRenderStart`, and if found, announce your custom event.
    public any function onRenderStart(m) {
      if ( arguments.m.event('myFormIsSubmitted') == 'true' ) {
        // announcing the event
        arguments.m.announceEvent('CustomFormSubmitted', arguments.m);
      }
    }
    

    If the form has been submitted, our customFormSubmitted event is announced, triggering any registered event handlers to execute.

    public any function onCustomFormSubmitted(m) {
      // you could do whatever you want here
      // including dumping out the entire event itself to inspect it
      // or simply dumping out the value of a specific form filed
      // and then halt the rest of the process (for example only)
      WriteDump(var=arguments.m.event('myField'), abort=true);
    }
    

    Rendering Events

    If you wish to "render" an event, in addition to sending a notification throughout Mura that something in particular is about to occur, or has just occurred, you are allowing for the possibility to render something to the browser. In other words, your code should be checking for a string to return, and if nothing is returned, then you'll most likely want to display something else by default.

    Syntax

    The basic syntax for rendering an event is:

    m.renderEvent('YourEvent');

    Examples

    There are several ways you could choose to render event output. The following example illustrates a simple way to output the result of a rendered event.

    <cfoutput>
      #esapiEncode('html', m.renderEvent('YourEvent'))#
    </cfoutput>

    The example below is typical of how Mura renders events in its own code.

    eventOutput = esapiEncode('html', m.renderEvent('YourEvent'));
    
    if ( Len(eventOutput) ) {
      WriteOutput(eventOutput);
    } else {
      // render something else / default output
    }

    Event Lifecycles

    Lifecycle events are generally triggered on every page request, and represent the execution of Mura's normal request flow. Mura consists of primarily two unique lifecycles: the Front-end Request Lifecycle, and the Admin Request Lifecycle. During the flow of these lifecycles, other contextual events are triggered, and are dependent upon the requested action that precedes it.

     

    Admin Request Lifecycle

    The administration area of Mura has a multitude of contextual events that could be triggered, depending on the requested action. For example, a user could be attempting to create new content, updating a user, or deleting a category. Each of these actions would trigger their own contextual events, in addition to the routine request flow outlined below.

    onGlobalRequestStart
      onAdminRequestStart
    
        onAdminHTMLHeadRender         // renders just before the closing </head> tag
    
          onAdminMFAChallengeRender   // Multi-factor Auth area of login screen
    
          onDashboardReplacement      // render a completely new dashboard
    
          onDashboardPrimaryTop       // renders in the top of the dashboard
          onDashboardPrimaryBottom    // renders in the bottom of the dashboard
          onDashboardSidebarTop       // renders in the top of the dashboard sidebar
          onDashboardSidebarBottom    // renders in the bottom of the dashboard sidebar
    
          onAdminNavMainRender        // render additional main nav menu items
          onFEToolbarExtensionRender  // render additional front-end toolbar menu items
          
          on{Type}SecondaryNavRender
          on{Type}{Subtype}SecondaryNavRender
    
          on{Type}{Subtype}NewContentMenuRender
          onNewContentMenuRender
    
        onAdminHTMLFootRender         // renders just before the closing </body> tag
    
      onAdminRequestEnd
    onGlobalRequestEnd
    

    Front-End Request Lifecycle

    While there may be any number of contextual events that are triggered, dependent upon the requested action, the events listed below generally occur during a typical front-end request.

    When it comes to the front-end request lifecycle, if you're most interested in the final string of code that will be returned to the browser, then you'll want to be aware of m.event('__MuraResponse__'). That's a double-underscore in front of, and after "MuraResponse". As noted in the lifecycle below, the "MuraResponse" will be sent to the browser.

    onGlobalRequestStart
      onSiteRequestInit
      onSiteRequestStart
    
        standardEnableLockdownValidator
          standardEnableLockdownHandler // if lockdown enabled
    
        standardSetContentHandler
          // if `previewid` exists
          standardSetPreviewHandler 
          // else
          standardSetAdTrackingHandler
    
          standardWrongFilenameValidator
            standardWrongFilenameHandler // if wrong filename
    
          standard404Validator
            standard404Handler // contextual: if content item not found
              onSite404 
        
        standardWrongDomainValidator
          standardWrongDomainHandler // if invalid domain
    
        standardTrackSessionValidator
          standardTrackSessionHandler // if session tracking enabled
    
        standardSetIsOnDisplayHandler
        standardDoActionsHandler // checks `doaction` (e.g., login, logout, etc.)
    
        standardSetPermissionsHandler
        standardRequireLoginValidator
          standardRequireLoginHandler // if login required
    
        standardSetLocaleHandler
        standardMobileValidator
          standardMobileHandler // if `request.muraMobileRequest` and no `altTheme`
    
        standardSetCommentPermissions
    
        standardDoResponseHandler
          standardForceSSLValidator
            standardForceSSLHandler // if necessary
    
          // This is a great place to put your logic
          // Mura begins compiling the code that will be returned to the browser
          onRenderStart
    
            // if content type is link
            standardLinkTranslationHandler
            // else if content type is file
            standardFileTranslationHandler
              standardFileTranslator
                onBeforeFileRender
                onAfterFileRender
            // else
            standardTranslationHandler  // sets m.event('__MuraResponse__')
              // if `returnformat` is JSON
              standardJSONTranslator
                onAPIResponse
                on{Type}APIResponse
                on{Type}{Subtype}APIResponse
                onAPIError  // if an error occurs
    
              // else
              standardHTMLTranslator // parses layout template and renders queues
                // other events could be announced, based on template code
                // `m.dspBody()` invokes several events (and is included in most templates)
                // if event('display') is `search`
                onSiteSearchRender
    
                // else if event('display') is `editprofile`
                onSiteEditProfileRender
    
                // else if event('display') is `login`
                onSiteLoginPromptRender
    
                // else if content is restricted and user not allowed
                onContentDenialRender
    
                // else if content is not on display
                onContentOfflineRender
    
                // else if `m.event('display')` is not an empty string
                onDisplayRender  // allows you to have custom displays
    
                // else
                  // default body rendering
    
                  on{Type}{Subtype}BodyRender  // e.g., onPageDefaultBodyRender
                  // if a string isn't returned, then
                  on{Type}BodyRender  // e.g., onPageBodyRender
    
                  // if a string still isn't returned, then
                  // Mura will look for files by content type
                  // `../{ThemeName}/content_types/{Type}_{Subtype}/index.cfm`
                  // Then, `../{ThemeName}/content_types/{Type}/index.cfm`
                  // and so forth.
                  // See the "Mura Rendering" section for more information
    
          // Mura has finished compiling the code to return to the browser
          // In other words, the train is about to leave the station ...
          onRenderEnd  // m.event('__MuraResponse__') is ready
    
      onSiteRequestEnd
    onGlobalRequestEnd
    

    Event Handlers

    Mura event handlers are simply ColdFusion components (CFCs), or files saved with the extension .cfc. They contain methods/functions, and may contain other variables and/or data. Most event handlers will contain one or more of Mura's event hooks, and/or custom event hooks.

    The event hooks are merely "announced" during specific points of a request. Registered event handlers will be parsed when the event they're registered for occurs, and if any event hooks are found, they will be executed. For example, if you have two registered even handlers, and both of them contain a method listening for the same event hook, both methods will execute, whenever the event is announced.

    As described in the Standard Events section, Mura's standard events handler is located under {context}/core/mura/Handler/standardEventsHandler.cfc. The methods may be viewed via Mura's Component API at http://www.getmura.com/component-api/7.1/index.html?mura/Handler/standardEventsHandler.html.

    Developers may have several Mura event handlers throughout your sites, themes, content types, modules, and plugins. As of Mura v7.1, you may also register your event handler(s) for specific entities. In addition, you can choose to register your event handlers by convention, or explicitly register them via a known event handler. Examples and options are described below.

    Example Event Handler

    With the exception of the "Site" event handler, or the "Theme" event handler, you can name your event handler anything you want, as long as it has the .cfc file extension. All event handlers should extend mura.cfobject. By doing so, you allow yourself the ability to leverage many of Mura's baked-in methods and functionality for working with Mura objects.

    CFScript-based .CFC Example

    component extends="mura.cfobject" {
    
      public any function onSomeEvent(m) {
        // arguments.m is "The Mura Scope"
        // Do something
      }
    
    }
    

    Tag-based .CFC Example

    <cfcomponent extends="mura.cfobject" output="false">
    
      <cffunction name="onSomeEvent" access="public" returntype="any">
        <cfargument name="m" hint="Mura Scope">
        <!--- Do something --->
      </cffunction>
    
    </cfcomponent>

    Plugin Event Handlers

    Plugin event handlers should extend mura.plugin.pluginGenericEventHandler, instead of using the typical mura.cfobject. Doing so allows you access to the plugin's own configuration information via variables.pluginConfig, as well as Mura's configuration data via variables.configBean.

    Registering event handlers in plugins is covered in the Plugins section.

    How To Register Event Handlers By Convention

    One way to register a Mura event handler is by convention. This means, if you create a .CFC file, and place it in a "known" location, Mura will automatically register it, and any event hooks contained within it will be executed when announced.

    The "Site" Event Handler

    Mura automatically checks every site for a specific file, labeled eventHandler.cfc,under the following location:

    {context}/sites/{SiteID}/eventHandler.cfc

    If this file is found, Mura will instantiate it on every front-end request. This means that any methods placed within this file should be specific to front-end requests. If you attempt to add any other request types here, for example, any events which occur only during the admin request lifecycle, they will not be executed.

    The "Theme" Event Handler

    Mura automatically checks the theme for a specific file, labeled eventHandler.cfc, under the following location:

    {context}/sites/{SiteID}/themes/{ThemeName}/eventHandler.cfc
    // OR
    {context}/themes/{ThemeName}/eventHandler.cfc
    

    Mura checks for this file during the onApplicationLoad event. When discovered, Mura instantiates it, and places the file into the application scope.

    Note: Since the file is only instantiated when the application loads, you must reload Mura anytime you make a change to the file itself.

    Content Type & Module Event Handlers

    Mura automatically scans both the content_types and modules directories for the following directory structure:

    ../model/handlers/{anyFilename}.cfc

    Any .cfc discovered under these ../model/handlers/ directories will be registered as event handlers. Currently, content_types and modules directories can reside under a site and/or a theme.

    // Sites
    {context}/sites/{SiteID}/content_types/{Type}_{Subtype}/model/handlers/
    {context}/sites/{SiteID}/modules/{module}/model/handlers/
    
    // Themes
    ../themes/{ThemeName}/content_types/{Type}_{Subtype}/model/handlers/
    ../themes/{ThemeName}/modules/{module}/model/handlers/

    Additional information regarding content types and modules can be found in the Mura Rendering section.

    How To Explicitly Register Event Handlers

    The basic syntax for explicitly registering a custom event handler is:

    m.getBean('pluginManager').addEventHandler( 
      {handlerObject or path}
      , {SiteID} 
    );
    

    For example, you may use one of the "known" registered event handlers, such as either the "Site" or "Theme" event handler. Then, using the onApplicationLoad event, you can register your custom event handler as follows:

    public any function onApplicationLoad(m) {
      // Assuming the customHandler.cfc file exists in the same directory as this file
      var myHandler = new customHandler();
    
      // Register the custom handler
      arguments.m.getBean('pluginManager').addEventHandler(
        myHandler
        , arguments.event.get('siteid')
      );
    }

    Entity Event Handlers

    Introduced in Mura v7.1, developers may register event handlers for specific beans/objects or entities such as content beans, user beans,  or even your own custom entities/objects. This allows developers the ability to create more focused business logic and code clarity. 

    For example, if you registered an event handler for "onRenderStart", your method will be invoked on each and every front-end page request, regardless of the content type, etc. Using targeted logic allows you to specify not only the object and type, you could also target a very specific object by loading it up, and attaching a custom event handler to it.

    To target a specific bean/object, we begin by using the "onApplicationLoad" event of a registered event handler.

    public any function onApplicationLoad(m} {
      // This is where our code will be
    }

    Then, we'll target a specific bean/object, and use either the "on" or "addEventHander" methods described below.

    on

    A bean/object helper method to dynamically register an event handler. Methods may be chained to attach multiple event handlers.

    Function Syntax

    m.getBean('someBean').on( eventName, fn )

    Parameters

    Parameter Type Req/Opt Description
    eventName string Req The name of the event you wish to register, without the "on" prefix. For example, if you wish to target the "onRenderStart" method, set this to "renderStart".
    fn function Req A function, or name of a function containing the code you wish to execute.

    Examples

    In this example, we're going to target a specific content bean, and attach a custom "onRenderStart" event handler to it.

    public any function onApplicationLoad(m) {
    
      m.getBean('content')
        .loadBy(title='Contact Us')
        .on('renderStart', function(m) {
          // do something
        });
    
    }

    In this example, we're targeting a user bean, and attaching a custom "onUserDelete" event handler.

    public any function onApplicationLoad(m) {
    
      m.getBean('user')
        .loadBy(useranme='steve')
        .on('userDelete', function(m) {
          // do something
        });
    
    }

    In this example, we're targeting the global config bean, and attaching a custom "onRenderEnd" event handler.

    public any function onApplicationLoad(m) {
    
      m.getBean('configBean')
        .on('onRenderEnd', function(m) {
          // do something
        });
    
      // OR
    
      m.globalConfig()
        .on('onRenderEnd', function(m) { 
          // do something   
         }); 
    
    }

    Note: When attaching event handlers to the global config bean, the event handler(s) will apply throughout the entire instance of Mura, across all sites.

    In this example, we're loading a content bean to target a specific form, and attaching a custom "onSubmitSave" event handler, and then chaining an additional handler for the "onSubmitResponseRender" event.

    public any function onApplicationLoad(m) {
    
      m.getBean('content')
        .loadBy(title='Information Request Form')
        .on('submitSave', function(m) {
          // do something
        })
        .on('submitResponseRender', function(m) { 
          // do something   
        });
    
    }

    In this example, we're targeting the global config bean, and attaching custom handlers for a custom ORM bean which will be invoked throughout all of Mura, regardless of which site is running.

    public any function onApplicationLoad(m) {
    
      m.getBean('configBean')
        .on('beforeWidgetSave', function(m) {
          // do something
        })
        .on('widgetSave', function(m) { 
          // do something   
        })
        .on('widgetSave', function(m) {   
          // do something   
        });
    
    }

    addEventHandler

    A bean/object helper method to dynamically register event handlers.

    Function Syntax

    m.getBean('someBean').addEventHandler( component )

    Parameters

    Parameter Type Req/Opt Description
    component struct Req A struct of key/value pairs of eventNames and functions to execute as event handlers for the specified eventName(s).

    Examples

    In this example, we're targeting the global config bean, and attaching custom handlers for a custom ORM bean which will be invoked throughout all of Mura, regardless of which site is running.

    public any function onApplicationLoad(m) {
    
      m.getBean('configBean')
        .addEventHandler({
          beforeWidgetSave = function(m) {
            // do something
          }
          , widgetSave = function(m) {
            // do something
          }
          , afterWidgetSave = function(m) {
            // do something
          }
        });
    
    }

    In this example, we're targeting a specific custom ORM bean and attaching some custom event handlers.

    public any function onApplicationLoad(m) {
    
      m.getBean('widget')
        .loadBy(id='someID')
        .addEventHandler({
          beforeSave = function(m) {
            // do something
          }
          , save = function(m) {
            // do something
          }
          , afterSave = function(m) {
            // do something
          }
        });
    
    }

    Mura's Event Log

    Mura has the capability to output an event log as a stack trace, including the time it took to execute, in milliseconds, directly to the browser. This feature is quite useful for troubleshooting and debugging, as well as discovering which areas of your code may benefit from applying performance optimization techniques.

    How to Enable/Disable the Stack Trace

    To enable the stack trace, you must first be logged in to Mura as an Administrator. Then, simply append /?showtrace=1 to the URL, and reload your browser. Once you do this, Mura will append a stack trace output to the end of your page, similar to the following example.

    Mura will then set a cookie, so you don't have to continually add it to each and every page you visit.

    If you wish to disable this feature, simply append /?showtrace=0 to the URL, and the stack trace should disappear after reloading your browser.

    How to Read/Use the Stack Trace

    The stack trace displays information useful for both debugging or troubleshooting, as well as identifying areas of code execution that might benefit from using some performance optimization techniques, such as caching, or possibly even rewriting the code to run more efficiently.

    Each item in the stack trace is listed in the order in which it was encountered during the execution of the request. Some items in the list simply display informational messages, and don't necessarily point to any specific line of code, while others output the entire path to the file or method being parsed.

    In the parenthesis to the right of each item in the list are two numbers. The number on the left indicates the number of milliseconds it took the server to parse the specific file or method, while the number on the right reflects the point in the total request (in milliseconds) when the file or method finished executing.

    So, for example, if you review the following stack trace, note item number 14. 

    Item number 14 indicates that Mura was parsing the two_column_SR.cfm layout template, and it took the server a total of 334 milliseconds to execute, and completed its execution at the 482nd millisecond.

    Item number 15 indicates a method call to contentRenderer.dspPrimaryNav, which in turn was invoked during the execution of parsing the two_column_SR.cfm file. The dspPrimaryNav method finished executing at the 255th millisecond. Subsequent items were then executed in the order listed.

    While you may not necessarily have the ability to optimize some of Mura's core methods, you can see the two_column_SR.cfm layout template is code you have direct control over. Maybe some of the code within the layout template could benefit from using a caching strategy, or some other form of performance optimization.

    Custom Stack Trace Points

    As a Mura developer, you may add your own custom messages to the stack trace output. This is useful for inspecting how long it takes for your custom code to execute, quickly and easily.

    The example below illustrates how to add your own trace point(s).

    <!--- Place this either at the top of your file, or at the beginning of a block of code you wish to trace --->
    <cfset myTracePoint = $.initTracePoint('your filename, method name, or other description to identify this trace point goes here ... this is what will output in the Stack Trace') />
    
    <!--- file content or block of code goes here --->
    
    <!--- Place this either at the bottom of your file, or at the end of a block of code you wish to trace --->
    <cfset m.commitTracePoint(myTracePoint) />

    This is an example stack trace output, using the above code in the footer.cfm layout template of the default theme.

    Summary

    Throughout this section, we covered the differences between lifecycle events and contextual events, the Mura "event" scope, and the wide variety of possible events that may occur during any given request, as well as how to register your own event handlers targeting the specific event(s) related to the task(s) you wish to accomplish. Finally, you learned how to create your own custom events, and how to use Mura's event log for debugging and performance optimization purposes.

    We hope that as you completed this section, you have a much better understanding on how you, as a Mura developer, can add to, or in some cases, even replace, Mura's own business logic and functionality.