Forum Discussion
I suppose it depends on what kind of logging you're hoping to accomplish.
For example, one option is to use the FreeMarker logging utilities if you're wanting some server-side logging to occur.
Alternatively, if you are wanting to have some client-side logging for troubleshooting/debugging purposes in the browser console (i.e. Developer Tools > Console), then you can leverage jQuery to do this.
In our environment, I created a macro called custom.macro.logging.ftl to simplify client-side logging in our customizations, which looks like this:
<#------------------------------------------------
Functions and Macros for Logging and Debugging
Created By: Jeff Shurtliff
Last Modified By: Jeff Shurtliff
Last Modified Date: 2020-11-03
------------------------------------------------->
<#-------------------- Macro: consoleLog -------------------->
<#-- This macro prints an entry to the browser JavaScript console (i.e. console.log) -->
<#macro consoleLog logEntry="">
<@liaAddScript>
; (function ($) {
console.log("${logEntry}");
})(LITHIUM.jQuery);
</@liaAddScript>
</#macro>
<#-------------------- Macro: consoleError -------------------->
<#-- This macro prints an error to the browser JavaScript console (i.e. console.error) -->
<#macro consoleError logEntry="">
<@liaAddScript>
; (function ($) {
console.error("${logEntry}");
})(LITHIUM.jQuery);
</@liaAddScript>
</#macro>
<#-------------------- Macro: consoleDebug -------------------->
<#-- This macro prints a debug message to the browser JavaScript console (i.e. console.debug) -->
<#macro consoleDebug logEntry="">
<@liaAddScript>
; (function ($) {
console.debug("${logEntry}");
})(LITHIUM.jQuery);
</@liaAddScript>
</#macro>
<#-------------------- Macro: consoleInfo -------------------->
<#-- This macro prints an info message to the browser JavaScript console (i.e. console.info) -->
<#macro consoleInfo logEntry="">
<@liaAddScript>
; (function ($) {
console.info("${logEntry}");
})(LITHIUM.jQuery);
</@liaAddScript>
</#macro>
<#-------------------- Macro: consoleWarn -------------------->
<#-- This macro prints a warning message to the browser JavaScript console (i.e. console.warn) -->
<#macro consoleWarn logEntry="">
<@liaAddScript>
; (function ($) {
console.warn("${logEntry}");
})(LITHIUM.jQuery);
</@liaAddScript>
</#macro>
Then in my other custom components/macros/functions I am able to easily generate log entries by importing the macro file and calling one of the macros above, as demonstrated below.
<#-- Import the macro file -->
<#import 'custom.macro.logging' as logging />
<#-- Attempt to get the user ID -->
<#attempt>
<#assign userId = user.id />
<@logging.consoleDebug "The User ID is ${userId}" />
<#recover>
<@logging.consoleError "Encountered an exception while retrieving the User ID" />
</#attempt>
Then while testing in the browser you can monitor the Console tab in Developer Tools and have a better understanding of what might be failing and why.
(I like to include the text "Encountered an exception while..." in error messages within the <#recover> directive because it reminds me that I should check out the Toolbox to see what the verbose FreeMarker error was so I can troubleshoot even further.)
I hope this helps!
I realized I forgot to comment on the other part of your question about getting "the kind of a variable" which I assume you mean the data type of a variable, e.g. string, hash, sequence, etc.
FreeMarker has some quite a few built-ins to check the data type of a variable, which are explained in the official documentation.
However, to avoid having to call a whole bunch of built-ins whenever I want to know the data type of one of my variables, I created the function below which really comes in handy.
<#-------------------- Function: checkDataType -------------------->
<#-- This function returns the data type of the object -->
<#function checkDataType object simple=false>
<#local dataType = "unknown" />
<#attempt>
<#if object?is_string>
<#local dataType = "string" />
<#elseif object?is_number>
<#local dataType = "number" />
<#elseif object?is_boolean>
<#local dataType = "boolean" />
<#elseif object?is_sequence>
<#local dataType = "sequence" />
<#if simple?? && !simple>
<#attempt>
<#local subType = checkDataType(object[0]) />
<#if subType?? && subType != "unknown">
<#local dataType = dataType + "+${subType}" />
</#if>
<#recover>
<@logging.consoleError "Encountered an exception when attempting to determine data subtype for object" />
</#attempt>
</#if>
<#elseif object?is_hash>
<#if simple?? && !simple && object?is_hash_ex>
<#local dataType = "extended_hash" />
<#else>
<#local dataType = "hash" />
</#if>
<#elseif object?is_date_like>
<#local dataType = "date_like" />
<#elseif object?is_method>
<#local dataType = "method" />
<#elseif object?is_macro>
<#local dataType = "macro_function" />
<#-- Correct syntax for checking marcos is checkDataType(macro) instead of checkDataType(<@macro></@macro>) -->
<#-- Correct syntax for checking functions is checkDataType(myFunc) instead of checkDataType(myFunc()) -->
</#if>
<#recover>
<@logging.consoleError "Encountered an exception when attempting to determine data type for object" />
</#attempt>
<#return dataType />
</#function>
This way I can use the function to quickly identify the data type and take action accordingly, such as in the example below. (I keep the function in a macro file called custom.macro.common.utils.ftl which is why you see it referenced as such below.)
<#-- Import common utilities -->
<#import 'custom.macro.common.utils' as commonUtils />
<#assign someVar = 12345 />
<#-- Ensure the variable below is a string -->
<#assign dataType = commonUtils.checkDataType(someVar) />
<#if dataType == 'number' || dataType == 'boolean'>
<#assign someVar = someVar?c />
</#if>
This is my variable: ${someVar}
Hope this helps!
Related Content
- 2 months ago
- 5 years ago
- 3 years ago
- 13 years ago