Click here for the API Reference documentation.
Logging Basics
Log Controls
Log Formats
Logging is a critical part of any embedded development framework. Most devices can't display error or warning messages and don't have a human user monitoring them. Even when a device does have a display and a user watching it, the log messages often don't help the device's primary user. And displaying messages on a screen doesn't support remote troubleshooting; especially when the device is hidden from view inside a piece of equipment or located in remote geographic regions.
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.
Levels
Basic Logging
Conditional Logging
Fatal Errors
Tracing
Result Code Text
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:
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).
There is a logging macro for each of the log levels:
For example,
LE_INFO("Obtained new IP address %s.", ipAddrStr);
Similar to the basic macros, but these contain a conditional expression as their first parameter. If this expression equals true, then the macro will generate this log output:
Instead of writing
if (result == -1) { LE_WARN("Failed to send message to server. Errno = %m."); }
you could write this:
LE_WARN_IF(result == -1, "Failed to send message to server. Errno = %m.");
There are some special logging macros that are intended for logging fatal errors:
For example,
if (NULL == objPtr) { LE_FATAL("Object pointer is NULL!"); } // Now I can go ahead and use objPtr, knowing that if it was NULL then LE_FATAL() would have // been called and LE_FATAL() never returns.
or,
LE_FATAL_IF(NULL == objPtr, "Object pointer is NULL!"); // Now I can go ahead and use objPtr, knowing that if it was NULL then LE_FATAL_IF() would not // have returned.
or,
LE_ASSERT(NULL != objPtr); // Now I can go ahead and use objPtr, knowing that if it was NULL then LE_ASSERT() would not // have returned.
Finally, a macro is provided for tracing:
This macro is special because it's independent of log level. Instead, trace messages are associated with a trace keyword. Tracing can be enabled and disabled based on these keywords.
If a developer wanted to trace the creation of "shape" objects in their GUI package, they could add trace statements like the following:
LE_TRACE(NewShapeTraceRef, "Created %p with position (%d,%d).", shapePtr, shapePtr->x, shapePtr->y);
The reference to the trace is obtained at start-up as follows:
NewShapeTraceRef = le_log_GetTraceRef("newShape");
This allows enabling and disabling these LE_TRACE() calls using the "newShape" keyword through configuration settings and runtime log control tools. See Log Controls below.
Applications can use LE_IS_TRACE_ENABLED(NewShapeTraceRef) to query whether a trace keyword is enabled.
These allow applications to hook into the trace management system to use it to implement sophisticated, application-specific tracing or profiling features.
The le_result_t macro supports printing an error condition in a human-readable text string.
result = le_foo_DoSomething(); if (result != LE_OK) { LE_ERROR("Failed to do something. Result = %d (%s).", result, LE_RESULT_TXT(result)); }
Log Control Tool
Log Control Configuration Settings
Environment Variables
LE_LOG_LEVEL
LE_LOG_TRACE
Programmatic Log Control
Log level filtering and tracing can be controlled at runtime using:
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".
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
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
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
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.
To set the log filter level, le_log_SetFilterLevel() is provided.
Trace keywords can be enabled and disabled programmatically by calling le_log_EnableTrace() and le_log_DisableTrace().
Log entries can also contain any of these:
Log messages have the following format:
Jan 3 02:37:56 INFO | processName[pid]/componentName T=threadName | fileName.c funcName() lineNum | Message
Copyright (C) Sierra Wireless, Inc. 2014. All rights reserved. Use of this work is subject to license.