How to - Use log functions

Most OpenAF code needs somehow to log it’s activity. The usual obvious choice is to use the print functions but once you start logging production code the requirements usually go beyond just simply outputing a string to the console/stdout.

To encapsule this extra functionality and, at the same time, keep the simplicity of the print functions OpenAF provides the log functions:

Function Quick description
log(msg, options) Logs the mgs as a normal information (INFO) message. One-time options can also be provided.
logErr(msg, options) Logs the mgs as an error (ERROR) message. One-time options can also be provided.
logWarn(msg, options) Logs the mgs as a warning (WARN) message. One-time options can also be provided.
lognl(msg, options) Same as the log function but won’t end with a new-line.

Examples:

log("This is a test") 
// 2020-01-02 12:13:14.567 | INFO | This is a test
logErr("Hups! There was an error!") 
// 2020-01-02 12:13:16.765 | ERROR | Hups! There was an error!
logWarn("Be careful...") 
// 2020-01-02 12:13:18.555 | WARN | Be careful...

As you might have noticed, for simplicity, there are 3 main loggging levels: INFO, ERROR and WARN.

Template-based log functions

Equivalent to the log* functions OpenAF also provides template-based (using the ow.template internal library) equivalent functions:

Function
tlog(msg, data, options)
tlogErr(msg, data, options)
tlogWarn(msg, data, options)
tlognl(msg, data, options)

The main difference is the extra data map-type parameter. This should be a map with the data to be used on the provided template on the msg parameter.

Simple example:


tlog("The current version is: {{version}}", { version: getVersion() })
// 2020-01-03 13:14:15.678 | INFO | The current version is: 20200102

If no data map is provided the current scope will be used:


var distribution = getDistribution()
tlog("The current distribution is: {{distribution}}")
// 2020-01-03 13:14:17.876 | INFO | The current distribution is: nightly

Log functions options

As described previously each log function can have one-time options provided but you can also change the current settings used using the function setLog(aOptionsMap).

The options available are:

Option Type Default Description
off boolean false If true no stdout/stderr output attempt will be executed
offInfo boolean false If true all INFO type messages won’t be output.
offError boolean false If true all ERROR type messages won’t be output.
offWarn boolean false If true all WARN type messages won’t be output.
dateFormat string “yyyy-MM-dd HH:mm:ss.SSS” This a ow.format.fromDate date format to be used.
dateTZ string   The time zone to use (refer to ow.format.fromDate). If not defined it will use the current Java
separator string ”|” The log fields separator to use (when using the default “human” format)
async boolean true If false logging will stop the execution to output the log message.
asyncLevel number 3 When async is true the asyncLevel determines the maximum number of queued log messages for logging. When the maximum number is reached the current execution will wait for log execution until the queued level is re-established.
profile boolean false Whenever a log message is captured the current Java memory and system load stats will also be gathered.
format string “human” This allows to change the stdout/stderr output format to other alternatives (e.g. json, slon)

Example setting global options:

setLog({ offInfo: true })
logWarn("The INFO messages are off")
// 2020-01-01 12:13:14.567 | WARN | The INFO messages are off
log("this is just a info message")
setLog({ offInfo: false })
logWarn("The INFO messages are now on")
// 2020-01-01 12:13:14.678 | WARN | The INFO messages are now on
log("this is just an info message")
// 2020-01-01 12:13:15.123 | INFO | this is just an info message

Example setting an on-time option:

logWarn("POINT OF NO RETURN!", { async: false })
// 2020-01-02 12:13:14.123 | WARN | POINT OF NO RETURN!

Logging to an OpenAF channel

It’s also possible to configure OpenAF to log to an OpenAF channel. This allows logging to fully use the OpenAF channels functionality including output to external targets like ElasticSearch and others.

To start the functionality you just need to use the function startLog(anOpenAFChannelSubscribeFunction, keepItems). The numeric keepItems argument (which defaults to 100) determines how many entries to keep internally (in memory) for the OpenAF channel functionality (if you specify -1 no life-cycle will be used).

The anOpenAFChannelSubscribeFunction will receive a key and a value map for each logged entry:

Key:

Field Type Description
n number Current system time in nanoseconds (nowNano())
t string The logging level (e.g. INFO, WARN, ERROR)

Value:

Field Type Description
n number Current system time in nanoseconds (nowNano())
d date The javascript date
t string The logging level (e.g. INFO, WARN, ERROR)
m string The logged message
freeMem number (if the option profile is true) the current Java free memory
totalMem number (if the option profile is true) the current Java total memory
systemLoad number (if the option profile is true) the current operating system load

If there is a need to stop the output of log messages to an OpenAF channel you can simply execute the function stopLog.

Example:

// Executes a custom function with the log data
startLog((aCh, aOp, aKey, aVal) => { if (aOp == "set") print(aVal.t + " --> " + aVal.m) })
// Turns off the standard stdout/stderr output
setLog({ off: true })
log("Script started")
// INFO --> Script started
// ...
log("Script ended")
// INFO --> Script ended
stopLog()

Check also

  • How to log to files with automated compression of old files and life-cycle/house-keeping management.