Logger for better Logs with VCF Automation Orchestrator

VCF Automation Orchestrator has a limitation with console logging because there is no way to dynamically output the name of an action or sub-workflow. The statement this.workflow.name can be used to get the name of a top-level workflow, but the same value would be used for all sub-workflows and Actions.

Several years ago, I wrote a post on my Simplygeek blog, demonstrating my solution to this problem. I still believe this is the best option available and will work without limitations.

My solution was to create a Logger class that can be imported into every Action and Workflow. This method allows for a standardised logging experience.

You can download my Logger module as a package here or as native JS here.

Below is an example of my Logger class being used on an Action called ‘addComputerToAD‘ that adds a computer object to Active Directory:

+00:00 INFO [Action: WindowsConfigService] Get activeDirectoryDomainName
+00:00 INFO [Action: WindowsConfigService] Found activeDirectoryDomainName: FREELANCERCOLO
+00:00 INFO [Action: WindowsConfigService] Get activeDirectoryServerOUDN
+00:00 INFO [Action: WindowsConfigService] Found activeDirectoryServerOUDN: OU=Windows,OU=flc-servers,DC=freelancercolo,DC=local
+00:00 INFO [Action: addComputerToAD] activeDirectoryDomainName: FREELANCERCOLO
+00:00 INFO [Action: addComputerToAD] activeDirectoryServerOUDN: OU=Windows,OU=flc-servers,DC=freelancercolo,DC=local
+00:00 INFO [Action: addComputerToAD] activeDirectoryServerOUName: Windows
+00:00 INFO [Action: addComputerToAD] Creating Active Directory computer account 'flcgs10' in OU path 'OU=Windows,OU=flc-servers,DC=freelancercolo,DC=local'
+00:00 DEBUG [Action: ActiveDirectoryService] Get Active Directory Host with name 'FREELANCERCOLO'
+00:00 DEBUG [Action: ActiveDirectoryService] Found Active Directory host 'FREELANCERCOLO'
+00:00 DEBUG [Action: ActiveDirectoryService] Finding Active Directory object with name 'Windows' of type 'OrganizationalUnit'
+00:00 DEBUG [Action: ActiveDirectoryService] Extending search using Distinguished Name 'OU=Windows,OU=flc-servers,DC=freelancercolo,DC=local'
+00:00 DEBUG [Action: ActiveDirectoryService] Finding Active Directory object with name 'flcgs10' of type 'ComputerAD'
+00:00 WARNING [Action: ActiveDirectoryService] No Active Directory object found for 'flcgs10' of type 'ComputerAD'
+00:00 DEBUG [Action: ActiveDirectoryService] Finding Active Directory object with name 'flcgs10' of type 'ComputerAD'
+00:00 DEBUG [Action: ActiveDirectoryService] Found Active Directory object: flcgs10
+00:00 INFO [Action: addComputerToAD] Successfully created Active Directory computer account.

In the example above, you can see multiple Actions sending log messages and the log type used (INFO, DEBUG and WARNING). These are additional Actions that are called from ‘addComputerToAD’. This makes the source of the log messages very clear and helps with troubleshooting.

Using Logger in an Action or Workflow simply requires the following to import the module, which should be added at the very top of an Action or Workflow scriptable task.

var log = new (System.getModule("com.simplygeek.vcf.orchestrator.logging").Logger())(
    "Action",
    "myTestAction"
);

You will need to set the two parameters as follows:

Parameters:

NameTypeDescription
logSourcestringThe source of the log. Must be set to ‘Action’ or ‘Workflow’
logNamestringThe name of the log message (the name of the Action or Workflow).

A new instance of the Logger class will be created and exposed by the variable ‘log‘ that can be used to send the log messages. Note that ‘log‘ can be changed to any value you require.

The only downside is that the logName has to manually be set to the actual name of the Action. If the Action was renamed, then the logMessage value would also need to be updated. For the 1000’s of Actions that I have written, this has been a very minor issue. Note that using arguments.callee to get the Action name dynamically causes problems with nested Actions.

To send a log message to the console, choose from one of the available methods, as follows:

log.info("my log test");
log.warn("my log test");
log.error("my log test");
log.debug("my log test");

The example above outputs the following:

Alternative Logging Methods

There is a logging alternative using the built-in setLogMarker method provided by the System class. LogMarker allows you to pass a string as a parameter to the setLogMarker method to set the prefix value for all log messages that follow.

The problem with using LogMarker is that it can throw errors if the Action is executed from the UI or if Actions are nested (calling one Action from another) with more complex deployments. These are deal breakers for me as this is how most of my code is structured.

You can find the details of the setLogMarker method at vroapi.

You can also read more about its implementation at CloudBlogger.

Thanks for reading, and please let me know your thoughts or if you found this post useful.