/ Build Apps

Logging API

The Legato Logging API provides a toolkit allowing code to be instrumented with error, warning, informational, and debugging messages. These messages can be turned on or off remotely and pushed or pulled from the device through a secure shell, cloud services interfaces, e-mail, SMS, etc.

Logging Basics

Legato's logging can be configured through this API, and there's also a command-line target log tool available.

Levels

Log messages are categorized according to the severity of the information being logged. A log message may be purely informational, describing something that is expected to occur from time-to-time during normal operation; or it may be a report of a fault that might have a significant negative impact on the operation of the system. To differentiate these, each log entry is associated with one of the following log levels:

Standard Out and Standard Error in Syslog

By default, app processes will have their stdout and stderr redirected to the syslog. Each process’s stdout will be logged at INFO severity level; it’s stderr will be logged at “ERR” severity level.

There are two limitations with this feature:

the PID reported in the logs generally refer to the PID of the process that generates the stdout/stderr message. If a process forks, then both the parent and child processes’ stdout/stderr will share the same connection to the syslog, and the parent’s PID will be reported in the logs for both processes.

stdout is line buffered when connected to a terminal, which means printf(“hello
”) will be printed to the terminal immediately. If stdout is connected to something like a pipe it's bulk buffered, which means a flush doesn't occur until the buffer is full.

To make your process line buffer stdout so that printf will show up in the logs as expected, the setlinebuf(stdout) system call can be used. Alternatively, fflush(stdout) can be called \ to force a flush of the stdout buffer.

This issue doesn't exist with stderr as stderr is never buffered.

Basic Logging

A series of macros are available to make logging easy.

None of them return anything.

All of them accept printf-style arguments, consisting of a format string followed by zero or more parameters to be printed (depending on the contents of the format string).

Fatal Errors

LE_FATAL_IF(condition, formatString, ...)
If the condition is true, kills the calling process after logging the message at EMERGENCY level.

LE_ASSERT(condition)
If the condition is true, does nothing. If the condition is false, logs the source code text of the condition at EMERGENCY level and kills the calling process.

LE_ASSERT_OK(condition)
If the condition is LE_OK (0), does nothing. If the condition is anything else, logs the a message at EMERGENCY level, containing the source code text of the condition, indicating that it did not evaluate to LE_OK, and kills the calling process.

Log Controls

Log Control Tool

The log control tool is used from the command-line to control the log level filtering, log output location (syslog/stderr), and tracing for different components within a running system.

Online documentation can be accessed from the log control tool by running "log help".

Here are some code samples.

To set the log level to INFO for a component "myComp" running in all processes with the name "myProc":

$ log level INFO myProc/myComp

To set the log level to DEBUG for a component "myComp" running in a process with PID 1234:

$ log level DEBUG 1234/myComp

To enable all LE_TRACE statements tagged with the keyword "foo" in a component called "myComp" running in all processes called "myProc":

$ log trace foo myProc/myComp

To disable the trace statements tagged with "foo" in the component "myComp" in processes called "myProc":

$ log stoptrace foo myProc/myComp

With all of the above examples "*" can be used in place of the process name or a component name (or both) to mean "all processes" and/or "all components".

Log Control Configuration Settings

Note

The configuration settings haven't been implemented yet.

Environment Variables

Environment variables can be used to control the default log settings, taking effect immediately at process start-up; even before the Log Control Daemon has been connected to.

Settings in the Log Control Daemon (applied through configuration and/or the log control tool) will override the environment variable settings when the process connects to the Log Control Daemon.

LE_LOG_LEVEL

LE_LOG_LEVEL can be used to set the default log filter level for all components in the process. Valid values are:

EMERGENCY

CRITICAL

ERROR

WARNING

INFO

DEBUG

For example,

$ export LE_LOG_LEVEL=DEBUG

LE_LOG_TRACE

LE_LOG_TRACE allows trace keywords to be enabled by default. The contents of this variable is a colon-separated list of keywords that should be enabled. Each keyword must be prefixed with a component name followed by a slash ('/').

For example,

$ export LE_LOG_TRACE=framework/fdMonitor:framework/logControl

Programmatic Log Control

Normally, configuration settings and the log control tool should suffice for controlling logging functionality. In some situations, it can be convenient to control logging programmatically in C.

App Crash Logs

When a process within an app faults or exits in error, a copy of the current syslog buffer is captured along with a core file of the process crash (if generated).

The core file maximum size is determined by the process settings maxCoreDumpFileBytes and maxFileBytes found in the processes section of your app's .adef file. By default, the maxCoreDumpFileBytes is set to 0, do not create a core file.

To help save the target from flash burnout, the syslog and core files are stored in the RAM FS under /tmp. When a crash occurs, this directory is created:

/tmp/legato_logs/

The files in that directory look like this:

core-myProc-1418694851
syslog-myApp-myProc-1418694851

To save on RAM space, only the most recent 4 copies of each file are preserved.

If the fault action for that app's process is to reboot the target, the output location is changed to this (and the most recent files in RAM space are preserved across reboots):