Logging

The Ballerina log module has four log levels with their priority in descending order as follows.

  1. ERROR
  2. WARN
  3. INFO
  4. DEBUG By default, all logs of the application that are INFO level and above are logged to the console.

Logging or Printing?

The io:println is a better option than logging when the goal is to display a help statement for a command line application.

  • Logs contain readily available diagnostic information, such as the time, module name, etc., of the logging event.
  • Logging can be selectively silenced by using the proper log levels.
  • Can set up log analytics.

Logging Best Practices

Set proper log level based on the application requirements.

Can have different log levels for different modules in the same package as well.

Suppose you want to set DEBUG level to the foo module, the ERROR level to the bar module, and WARN level to the rest of the modules in the package. You can achieve this by updating the Config.toml file as follows.

[ballerina.log]
level = "WARN"


[[ballerina.log.modules]]
name = "myorgname/mypackagename.foo"
level = "DEBUG"


[[ballerina.log.modules]]
name = "myorg/mypackagename.bar"
level = "ERROR"

Make use of string templates if the values need to be concatenated

Bad Code

int delay = 15;
int timeout = 30;
log:printInfo("Application started with delay " + delay.toString() + " seconds and timeout " + timeout.toString() + "seconds" );

Good Code

int delay = 15;
int timeout = 30;
log:printInfo(string `Application started with delay ${delay} seconds and timeout ${timeout} seconds`);

Make use of key-value pairs when logging

Even better log outputs can be generated if the key-value pairs are used.

Good Code

int delay = 15;
int timeout = 30;
log:printInfo("Application started", Delay = delay, Timeout = timeout);

Make use of function pointers to improve the performance

Bad Code

  • Suppose the current log level is INFO and there is a DEBUG log that logs a value returned from a function with heavy computations.
  • Since DEBUG level logs are not printed due to log level; ideally, the function with heavy computations should not be executed.
  • But in the below code, still, the getDuration function is executed even though the debug log line is printed.
import ballerina/log;
import ballerina/random;

public function main() {
    float duration = getDutration();
    log:printDebug("Checking the duration", duration = duration);
}

function getDutration() returns float {
    log:printInfo("Calculating duration");
    return random:createDecimal() * 100.0;
}

Good Code

  • Can avoid this by passing a pointer to the function as a value in a key/value pair like follows.
import ballerina/log;
import ballerina/random;

public function main() {
    log:printDebug("Checking the duration", duration = isolated function() returns float {
                       log:printInfo("Calculating duration optimally");
                       return random:createDecimal() * 100.0;});
}

See Also: