le_log.h

Go to the documentation of this file.
1 /**
2  * @page c_logging Logging API
3  *
4  * @ref le_log.h "API Reference" <br>
5  *
6  * The Legato Logging API provides a toolkit allowing code to be instrumented with error, warning,
7  * informational, and debugging messages. These messages can be turned on or off remotely and pushed or pulled
8  * from the device through a secure shell, cloud services interfaces, e-mail, SMS, etc.
9  *
10  * @section c_log_logging Logging Basics
11  *
12  * Legato's logging can be configured through this API, and there's also a command-line target
13  * @ref toolsTarget_log tool available.
14  *
15  * @subsection c_log_levels Levels
16  *
17  * Log messages are categorized according to the severity of the information being logged.
18  * A log message may be purely informational, describing something that is
19  * expected to occur from time-to-time during normal operation; or it may be a report of a fault
20  * that might have a significant negative impact on the operation of the system. To
21  * differentiate these, each log entry is associated with one of the following log levels:
22  *
23  * - @ref LE_LOG_DEBUG "DEBUG":
24  * Handy for troubleshooting.
25  * - @ref LE_LOG_INFO "INFORMATION":
26  * Expected to happen; can be interesting even when not troubleshooting.
27  * - @ref LE_LOG_WARN "WARNING":
28  * Should not normally happen; may not have any real impact on system performance.
29  * - @ref LE_LOG_ERR "ERROR":
30  * Fault that may result in noticeable short-term system misbehaviour. Needs attention.
31  * - @ref LE_LOG_CRIT "CRITICAL":
32  * Fault needs urgent attention. Will likely result in system failure.
33  * - @ref LE_LOG_EMERG "EMERGENCY":
34  * Definite system failure.
35  *
36  * @subsection c_log_basic_defaultSyslog Standard Out and Standard Error in Syslog
37  *
38  * By default, app processes will have their @c stdout and @c stderr redirected to the @c syslog. Each
39  * process’s stdout will be logged at INFO severity level; it’s stderr will be logged at
40  * “ERR” severity level.
41 
42  * There are two limitations with this feature:
43  * - the PID reported in the logs generally refer to the PID of the process that
44  * generates the stdout/stderr message. If a process forks, then both the parent and
45  * child processes’ stdout/stderr will share the same connection to the syslog, and the parent’s
46  * PID will be reported in the logs for both processes.
47  * - stdout is line buffered when connected to a terminal, which means
48  * <code>printf(“hello\n”)</code> will be printed to the terminal immediately. If stdout is
49  * connected to something like a pipe it's bulk buffered, which means a flush doesn't occur until the buffer is full.
50  *
51  * To make your process line buffer stdout so that printf will show up in the logs as expected,
52  * the @c setlinebuf(stdout) system call can be used. Alternatively, @c fflush(stdout) can be called \
53  * to force a flush of the stdout buffer.
54  *
55  * This issue doesn't exist with stderr as stderr is never buffered.
56  *
57  * @subsection c_log_basic_logging Basic Logging
58  *
59  * A series of macros are available to make logging easy.
60  *
61  * None of them return anything.
62  *
63  * All of them accept printf-style arguments, consisting of a format string followed by zero or more
64  * parameters to be printed (depending on the contents of the format string).
65  *
66  * There is a logging macro for each of the log levels:
67  *
68  * - @ref LE_DEBUG(formatString, ...)
69  * - @ref LE_INFO(formatString, ...)
70  * - @ref LE_WARN(formatString, ...)
71  * - @ref LE_ERROR(formatString, ...)
72  * - @ref LE_CRIT(formatString, ...)
73  * - @ref LE_EMERG(formatString, ...)
74  *
75  * For example,
76  * @code
77  * LE_INFO("Obtained new IP address %s.", ipAddrStr);
78  * @endcode
79  *
80  * @subsection c_log_conditional_logging Conditional Logging
81  *
82  * Similar to the basic macros, but these contain a conditional expression as their first parameter. If this expression equals
83  * true, then the macro will generate this log output:
84  *
85  * - @ref LE_DEBUG_IF(expression, formatString, ...)
86  * - @ref LE_INFO_IF(expression, formatString, ...)
87  * - @ref LE_WARN_IF(expression, formatString, ...)
88  * - @ref LE_ERROR_IF(expression, formatString, ...)
89  * - @ref LE_CRIT_IF(expression, formatString, ...)
90  * - @ref LE_EMERG_IF(expression, formatString, ...)
91  *
92  * Instead of writing
93  * @code
94  * if (result == -1)
95  * {
96  * LE_WARN("Failed to send message to server. Errno = %m.");
97  * }
98  * @endcode
99  *
100  * you could write this:
101  * @code
102  * LE_WARN_IF(result == -1, "Failed to send message to server. Errno = %m.");
103  * @endcode
104  *
105  * @subsection c_log_loging_fatals Fatal Errors
106  *
107  * There are some special logging macros intended for fatal errors:
108  *
109  * - @ref LE_FATAL(formatString, ...) \n
110  * Always kills the calling process after logging the message at EMERGENCY level (never returns).
111  * - @ref LE_FATAL_IF(condition, formatString, ...) \n
112  * If the condition is true, kills the calling process after logging the message at EMERGENCY
113  * level.
114  * - @ref LE_ASSERT(condition) \n
115  * If the condition is true, does nothing. If the condition is false, logs the source
116  * code text of the condition at EMERGENCY level and kills the calling process.
117  * - @ref LE_ASSERT_OK(condition) \n
118  * If the condition is LE_OK (0), does nothing. If the condition is anything else, logs the
119  * a message at EMERGENCY level, containing the source code text of the condition, indicating
120  * that it did not evaluate to LE_OK, and kills the calling process.
121  *
122  * For example,
123  * @code
124  * if (NULL == objPtr)
125  * {
126  * LE_FATAL("Object pointer is NULL!");
127  * }
128  *
129  * // Now I can go ahead and use objPtr, knowing that if it was NULL then LE_FATAL() would have
130  * // been called and LE_FATAL() never returns.
131  * @endcode
132  *
133  * or,
134  *
135  * @code
136  * LE_FATAL_IF(NULL == objPtr, "Object pointer is NULL!");
137  *
138  * // Now I can go ahead and use objPtr, knowing that if it was NULL then LE_FATAL_IF() would not
139  * // have returned.
140  * @endcode
141  *
142  * or,
143  *
144  * @code
145  * LE_ASSERT(NULL != objPtr);
146  *
147  * // Now I can go ahead and use objPtr, knowing that if it was NULL then LE_ASSERT() would not
148  * // have returned.
149  * @endcode
150  *
151  * @subsection c_log_tracing Tracing
152  *
153  * Finally, a macro is provided for tracing:
154  *
155  * - @ref LE_TRACE(traceRef, string, ...)
156  *
157  * This macro is special because it's independent of log level. Instead, trace messages are
158  * associated with a trace keyword. Tracing can be enabled and disabled based on these keywords.
159  *
160  * If a developer wanted to trace the creation of "shape"
161  * objects in their GUI package, they could add trace statements like the following:
162  *
163  * @code
164  * LE_TRACE(NewShapeTraceRef, "Created %p with position (%d,%d).", shapePtr, shapePtr->x, shapePtr->y);
165  * @endcode
166  *
167  * The reference to the trace is obtained at start-up as follows:
168  *
169  * @code
170  * NewShapeTraceRef = le_log_GetTraceRef("newShape");
171  * @endcode
172  *
173  * This allows enabling and disabling these LE_TRACE() calls using the "newShape" keyword
174  * through configuration settings and runtime log control tools. See @ref c_log_controlling below.
175  *
176  * Applications can use @ref LE_IS_TRACE_ENABLED(NewShapeTraceRef) to query whether
177  * a trace keyword is enabled.
178  *
179  * These allow apps to hook into the trace management system to use it to implement
180  * sophisticated, app-specific tracing or profiling features.
181  *
182  * @subsection c_log_resultTxt Result Code Text
183  *
184  * The @ref le_result_t macro supports printing an error condition in a human-readable text string.
185  *
186  * @code
187  * result = le_foo_DoSomething();
188  *
189  * if (result != LE_OK)
190  * {
191  * LE_ERROR("Failed to do something. Result = %d (%s).", result, LE_RESULT_TXT(result));
192  * }
193  * @endcode
194  *
195  *
196  * @section c_log_controlling Log Controls
197  *
198  * Log level filtering and tracing can be controlled at runtime using:
199  * - the command-line Log Control Tool (@ref toolsTarget_log)
200  * - configuration settings
201  * - environment variables
202  * - function calls.
203  *
204  * @subsection c_log_control_tool Log Control Tool
205  *
206  * The log control tool is used from the command-line to control the log
207  * level filtering, log output location (syslog/stderr), and tracing for different components
208  * within a running system.
209  *
210  * Online documentation can be accessed from the log control tool by running "log help".
211  *
212  * Here are some code samples.
213  *
214  * To set the log level to INFO for a component "myComp" running in all processes with the
215  * name "myProc":
216  * @verbatim
217 $ log level INFO myProc/myComp
218 @endverbatim
219  *
220  * To set the log level to DEBUG for a component "myComp" running in a process with PID 1234:
221  * @verbatim
222 $ log level DEBUG 1234/myComp
223 @endverbatim
224  *
225  * To enable all LE_TRACE statements tagged with the keyword "foo" in a component called "myComp"
226  * running in all processes called "myProc":
227  * @verbatim
228 $ log trace foo myProc/myComp
229 @endverbatim
230  *
231  * To disable the trace statements tagged with "foo" in the component "myComp" in processes
232  * called "myProc":
233  * @verbatim
234 $ log stoptrace foo myProc/myComp
235 @endverbatim
236  *
237  * With all of the above examples "*" can be used in place of the process name or a component
238  * name (or both) to mean "all processes" and/or "all components".
239  *
240  * @subsection c_log_control_config Log Control Configuration Settings
241  *
242  * @note The configuration settings haven't been implemented yet.
243  *
244  * @todo Write @ref c_log_control_config section.
245  *
246  * @subsection c_log_control_environment_vars Environment Variables
247  *
248  * Environment variables can be used to control the default log settings, taking effect immediately
249  * at process start-up; even before the Log Control Daemon has been connected to.
250  *
251  * Settings in the Log Control Daemon (applied through configuration and/or the log control tool)
252  * will override the environment variable settings when the process connects to the Log
253  * Control Daemon.
254  *
255  * @subsubsection c_log_control_env_level LE_LOG_LEVEL
256  *
257  * @c LE_LOG_LEVEL can be used to set the default log filter level for all components
258  * in the process. Valid values are:
259  *
260  * - @c EMERGENCY
261  * - @c CRITICAL
262  * - @c ERROR
263  * - @c WARNING
264  * - @c INFO
265  * - @c DEBUG
266  *
267  * For example,
268  * @verbatim
269 $ export LE_LOG_LEVEL=DEBUG
270 @endverbatim
271  *
272  * @subsubsection c_log_control_env_trace LE_LOG_TRACE
273  *
274  * @c LE_LOG_TRACE allows trace keywords to be enabled by default. The contents of this
275  * variable is a colon-separated list of keywords that should be enabled. Each keyword
276  * must be prefixed with a component name followed by a slash ('/').
277  *
278  * For example,
279  * @verbatim
280 $ export LE_LOG_TRACE=framework/fdMonitor:framework/logControl
281 @endverbatim
282  *
283  * @subsection c_log_control_functions Programmatic Log Control
284  *
285  * Normally, configuration settings and the log control tool should suffice for controlling
286  * logging functionality. In some situations, it can be convenient
287  * to control logging programmatically in C.
288  *
289  * le_log_SetFilterLevel() sets the log filter level.
290  *
291  * le_log_GetFilterLevel() gets the log filter level.
292  *
293  * Trace keywords can be enabled and disabled programmatically by calling
294  * @ref le_log_EnableTrace() and @ref le_log_DisableTrace().
295  *
296  *
297  * @section c_log_format Log Formats
298  *
299  * Log entries can also contain any of these:
300  * - timestamp (century, year, month, day, hours, minutes, seconds, milliseconds, microseconds)
301  * - level (debug, info, warning, etc.) @b or trace keyword
302  * - process ID
303  * - component name
304  * - thread name
305  * - source code file name
306  * - function name
307  * - source code line number
308  *
309  * Log messages have the following format:
310  *
311  * @verbatim
312 Jan 3 02:37:56 INFO | processName[pid]/componentName T=threadName | fileName.c funcName() lineNum | Message
313 @endverbatim
314  *
315  * @section c_log_debugFiles App Crash Logs
316 
317 * When a process within an app faults or exits in error, a copy of the current syslog buffer
318 * is captured along with a core file of the process crash (if generated).
319 
320 * The core file maximum size is determined by the process settings @c maxCoreDumpFileBytes and
321 * @c maxFileBytes found in the processes section of your app's @c .adef file. By default, the
322 * @c maxCoreDumpFileBytes is set to 0, do not create a core file.
323 
324 * To help save the target from flash burnout, the syslog and core files are stored in the RAM
325 * FS under /tmp. When a crash occurs, this directory is created:
326 
327  @verbatim
328  /tmp/legato_logs/
329  @endverbatim
330 
331 * The files in that directory look like this:
332 
333  @verbatim
334  core-myProc-1418694851
335  syslog-myApp-myProc-1418694851
336  @endverbatim
337 
338 * To save on RAM space, only the most recent 4 copies of each file are preserved.
339 
340 * If the fault action for that app's process is to reboot the target, the output location is changed to
341 * this (and the most recent files in RAM space are preserved across reboots):
342 
343  @verbatim
344  /mnt/flash/legato_logs/
345  @endverbatim
346 
347 *
348  * @todo May need to support log format configuration through command-line arguments or a
349  * configuration file.
350  *
351  * @todo Write @ref c_log_retrieving section
352  *
353  * <HR>
354  *
355  * Copyright (C) Sierra Wireless Inc.
356  */
357 
358 
359 /** @file le_log.h
360  *
361  * Legato @ref c_logging include file.
362  *
363  * Copyright (C) Sierra Wireless Inc.
364  */
365 
366 #ifndef LEGATO_LOG_INCLUDE_GUARD
367 #define LEGATO_LOG_INCLUDE_GUARD
368 
369 //--------------------------------------------------------------------------------------------------
370 /**
371  * Local definitions that should not be used directly.
372  */
373 //--------------------------------------------------------------------------------------------------
374 typedef enum
375 {
376  LE_LOG_DEBUG, ///< Debug message.
377  LE_LOG_INFO, ///< Informational message. Normally expected.
378  LE_LOG_WARN, ///< Warning. Possibly indicates a problem. Should be addressed.
379  LE_LOG_ERR, ///< Error. Definitely indicates a fault that needs to be addressed.
380  /// Possibly resulted in a system failure.
381  LE_LOG_CRIT, ///< Critical error. Fault that almost certainly has or will result in a
382  /// system failure.
383  LE_LOG_EMERG ///< Emergency. A fatal error has occurred. A process is being terminated.
384 }
386 
387 
388 //--------------------------------------------------------------------------------------------------
389 /// @cond HIDDEN_IN_USER_DOCS
390 
391 typedef struct le_log_Session* le_log_SessionRef_t;
392 
393 typedef struct le_log_Trace* le_log_TraceRef_t;
394 
395 void _le_log_Send
396 (
397  const le_log_Level_t level,
398  const le_log_TraceRef_t traceRef,
399  le_log_SessionRef_t logSession,
400  const char* filenamePtr,
401  const char* functionNamePtr,
402  const unsigned int lineNumber,
403  const char* formatPtr,
404  ...
405 ) __attribute__ ((format (printf, 7, 8)));
406 
407 le_log_TraceRef_t _le_log_GetTraceRef
408 (
409  le_log_SessionRef_t logSession,
410  const char* keyword
411 );
412 
413 void _le_log_SetFilterLevel
414 (
415  le_log_SessionRef_t logSession,
416  le_log_Level_t level
417 );
418 
419 void _le_LogData
420 (
421  const uint8_t* dataPtr, // The buffer address to be dumped
422  int dataLength, // The data length of buffer
423  const char* filenamePtr, // The name of the source file that logged the message.
424  const char* functionNamePtr, // The name of the function that logged the message.
425  const unsigned int lineNumber // The line number in the source file that logged the message.
426 );
427 
428 
429 //--------------------------------------------------------------------------------------------------
430 /**
431  * Filtering session reference for the current source file.
432  *
433  * @note The real name of this is passed in by the build system. This way it can be a unique
434  * variable for each component.
435  */
436 //--------------------------------------------------------------------------------------------------
437 #ifdef __cplusplus
438 extern
439 #endif
440 LE_SHARED le_log_SessionRef_t LE_LOG_SESSION;
441 
442 //--------------------------------------------------------------------------------------------------
443 /**
444  * Filtering level for the current source file.
445  *
446  * @note The real name of this is passed in by the build system. This way it can be a unique
447  * variable for each component.
448  */
449 //--------------------------------------------------------------------------------------------------
450 #ifdef __cplusplus
451 extern
452 #endif
453 LE_SHARED le_log_Level_t* LE_LOG_LEVEL_FILTER_PTR;
454 
455 
456 /// @endcond
457 //--------------------------------------------------------------------------------------------------
458 
459 //--------------------------------------------------------------------------------------------------
460 /**
461  * Internal macro to filter out messages that do not meet the current filtering level.
462  */
463 //--------------------------------------------------------------------------------------------------
464 #define _LE_LOG_MSG(level, formatString, ...) \
465  do { \
466  if ((LE_LOG_LEVEL_FILTER_PTR == NULL) || (level >= *LE_LOG_LEVEL_FILTER_PTR)) \
467  _le_log_Send(level, NULL, LE_LOG_SESSION, STRINGIZE(LE_FILENAME), __func__, __LINE__, \
468  formatString, ##__VA_ARGS__); \
469  } while(0)
470 
471 
472 //--------------------------------------------------------------------------------------------------
473 /** @internal
474  * The following macros are used to send log messages at different severity levels:
475  *
476  * Accepts printf-style arguments, consisting of a format string followed by zero or more parameters
477  * to be printed (depending on the contents of the format string).
478  */
479 //--------------------------------------------------------------------------------------------------
480 
481 /** @copydoc LE_LOG_DEBUG */
482 #define LE_DEBUG(formatString, ...) _LE_LOG_MSG(LE_LOG_DEBUG, formatString, ##__VA_ARGS__)
483 /** @copydoc LE_LOG_DATA */
484 #define LE_DUMP(dataPtr, dataLength) _le_LogData(dataPtr, dataLength, STRINGIZE(LE_FILENAME), __func__, __LINE__)
485 /** @copydoc LE_LOG_INFO */
486 #define LE_INFO(formatString, ...) _LE_LOG_MSG(LE_LOG_INFO, formatString, ##__VA_ARGS__)
487 /** @copydoc LE_LOG_WARN */
488 #define LE_WARN(formatString, ...) _LE_LOG_MSG(LE_LOG_WARN, formatString, ##__VA_ARGS__)
489 /** @copydoc LE_LOG_ERR */
490 #define LE_ERROR(formatString, ...) _LE_LOG_MSG(LE_LOG_ERR, formatString, ##__VA_ARGS__)
491 /** @copydoc LE_LOG_CRIT */
492 #define LE_CRIT(formatString, ...) _LE_LOG_MSG(LE_LOG_CRIT, formatString, ##__VA_ARGS__)
493 /** @copydoc LE_LOG_EMERG */
494 #define LE_EMERG(formatString, ...) _LE_LOG_MSG(LE_LOG_EMERG, formatString, ##__VA_ARGS__)
495 
496 
497 //--------------------------------------------------------------------------------------------------
498 /** @internal
499  * The following macros are used to send log messages at different severity levels conditionally.
500  * If the condition is true the message is logged. If the condition is false the message is not
501  * logged.
502  *
503  * Accepts printf-style arguments, consisting of a format string followed by zero or more parameters
504  * to be printed (depending on the contents of the format string).
505  */
506 //--------------------------------------------------------------------------------------------------
507 
508 /** @ref LE_DEBUG if condition is met. */
509 #define LE_DEBUG_IF(condition, formatString, ...) \
510  if (condition) { _LE_LOG_MSG(LE_LOG_DEBUG, formatString, ##__VA_ARGS__); }
511 /** @ref LE_INFO if condition is met. */
512 #define LE_INFO_IF(condition, formatString, ...) \
513  if (condition) { _LE_LOG_MSG(LE_LOG_INFO, formatString, ##__VA_ARGS__); }
514 /** @ref LE_WARN if condition is met. */
515 #define LE_WARN_IF(condition, formatString, ...) \
516  if (condition) { _LE_LOG_MSG(LE_LOG_WARN, formatString, ##__VA_ARGS__); }
517 /** @ref LE_ERROR if condition is met. */
518 #define LE_ERROR_IF(condition, formatString, ...) \
519  if (condition) { _LE_LOG_MSG(LE_LOG_ERR, formatString, ##__VA_ARGS__); }
520 /** @ref LE_CRIT if condition is met. */
521 #define LE_CRIT_IF(condition, formatString, ...) \
522  if (condition) { _LE_LOG_MSG(LE_LOG_CRIT, formatString, ##__VA_ARGS__); }
523 /** @ref LE_EMERG if condition is met. */
524 #define LE_EMERG_IF(condition, formatString, ...) \
525  if (condition) { _LE_LOG_MSG(LE_LOG_EMERG, formatString, ##__VA_ARGS__); }
526 
527 
528 //--------------------------------------------------------------------------------------------------
529 /**
530  * Log fatal errors by killing the calling process after logging the message at EMERGENCY
531  * level. This macro never returns.
532  *
533  * Accepts printf-style arguments, consisting of a format string followed by zero or more parameters
534  * to be printed (depending on the contents of the format string).
535  */
536 //--------------------------------------------------------------------------------------------------
537 #define LE_FATAL(formatString, ...) \
538  { LE_EMERG(formatString, ##__VA_ARGS__); exit(EXIT_FAILURE); }
539 
540 
541 //--------------------------------------------------------------------------------------------------
542 /**
543  * This macro does nothing if the condition is false, otherwise it logs the message at EMERGENCY
544  * level and then kills the calling process.
545  *
546  * Accepts printf-style arguments, consisting of a format string followed by zero or more parameters
547  * to be printed (depending on the contents of the format string).
548  */
549 //--------------------------------------------------------------------------------------------------
550 #define LE_FATAL_IF(condition, formatString, ...) \
551  if (condition) { LE_FATAL(formatString, ##__VA_ARGS__) }
552 
553 
554 //--------------------------------------------------------------------------------------------------
555 /**
556  * This macro does nothing if the condition is true, otherwise it logs the condition expression as
557  * a message at EMERGENCY level and then kills the calling process.
558  */
559 //--------------------------------------------------------------------------------------------------
560 #define LE_ASSERT(condition) \
561  if (!(condition)) { LE_FATAL("Assert Failed: '%s'", #condition) }
562 
563 
564 //--------------------------------------------------------------------------------------------------
565 /**
566  * This macro does nothing if the condition is LE_OK (0), otherwise it logs that the expression did
567  * not evaluate to LE_OK (0) in a message at EMERGENCY level and then kills the calling process.
568  */
569 //--------------------------------------------------------------------------------------------------
570 #define LE_ASSERT_OK(condition) \
571  if ((condition) != LE_OK) { LE_FATAL("Assert Failed: '%s' is not LE_OK (0)", #condition) }
572 
573 
574 //--------------------------------------------------------------------------------------------------
575 /**
576  * Get a null-terminated, printable string representing an le_result_t value.
577  *
578  * For example, LE_RESULT_TXT(LE_NOT_PERMITTED) would return a pointer to a string containing
579  * "LE_NOT_PERMITTED".
580  *
581  * "(unknown)" will be returned if the value given is out of range.
582  *
583  * @return Pointer to a string constant.
584  */
585 //--------------------------------------------------------------------------------------------------
586 #define LE_RESULT_TXT(v) _le_log_GetResultCodeString(v)
587 
588 /// Function that does the real work of translating result codes. See @ref LE_RESULT_TXT.
589 const char* _le_log_GetResultCodeString
590 (
591  le_result_t resultCode ///< [in] Result code value to be translated.
592 );
593 
594 
595 //--------------------------------------------------------------------------------------------------
596 /**
597  * Queries whether or not a trace keyword is enabled.
598  *
599  * @return
600  * true if the keyword is enabled.
601  * false otherwise.
602  */
603 //--------------------------------------------------------------------------------------------------
604 #define LE_IS_TRACE_ENABLED(traceRef) (le_log_IsTraceEnabled(traceRef))
605 
606 
607 //--------------------------------------------------------------------------------------------------
608 /**
609  * Logs the string if the keyword has been enabled by a runtime tool or configuration setting.
610  */
611 //--------------------------------------------------------------------------------------------------
612 #define LE_TRACE(traceRef, string, ...) \
613  if (le_log_IsTraceEnabled(traceRef)) \
614  { \
615  _le_log_Send((le_log_Level_t)-1, \
616  traceRef, \
617  LE_LOG_SESSION, \
618  STRINGIZE(LE_FILENAME), \
619  __func__, \
620  __LINE__, \
621  string, \
622  ##__VA_ARGS__); \
623  }
624 
625 
626 //--------------------------------------------------------------------------------------------------
627 /**
628  * Gets a reference to a trace keyword's settings.
629  *
630  * @return Trace reference.
631  **/
632 //--------------------------------------------------------------------------------------------------
633 static inline le_log_TraceRef_t le_log_GetTraceRef
634 (
635  const char* keywordPtr ///< [IN] Pointer to the keyword string.
636 )
637 {
638  return _le_log_GetTraceRef(LE_LOG_SESSION, keywordPtr);
639 }
640 
641 
642 //--------------------------------------------------------------------------------------------------
643 /**
644  * Determines if a trace is currently enabled.
645  *
646  * @return true if enabled, false if not.
647  **/
648 //--------------------------------------------------------------------------------------------------
649 static inline bool le_log_IsTraceEnabled
650 (
651  const le_log_TraceRef_t traceRef ///< [IN] Trace reference obtained from le_log_GetTraceRef().
652 )
653 {
654  return *((bool*)traceRef);
655 }
656 
657 
658 //--------------------------------------------------------------------------------------------------
659 /**
660  * Sets the log filter level for the calling component.
661  *
662  * @note Normally not necessary as the log filter level can be controlled at
663  * runtime using the log control tool, and can be persistently configured.
664  * See @ref c_log_controlling.
665  **/
666 //--------------------------------------------------------------------------------------------------
667 static inline void le_log_SetFilterLevel
668 (
669  le_log_Level_t level ///< [IN] Log filter level to apply to the current log session.
670 )
671 {
672  _le_log_SetFilterLevel(LE_LOG_SESSION, level);
673 }
674 
675 
676 //--------------------------------------------------------------------------------------------------
677 /**
678  * Gets the log filter level for the calling component.
679  **/
680 //--------------------------------------------------------------------------------------------------
682 (
683  void
684 )
685 {
686  if (LE_LOG_LEVEL_FILTER_PTR != NULL)
687  {
688  return *LE_LOG_LEVEL_FILTER_PTR;
689  }
690  else
691  {
692  return LE_LOG_INFO; // Default.
693  }
694 }
695 
696 
697 //--------------------------------------------------------------------------------------------------
698 /**
699  * Enables a trace.
700  *
701  * @note Normally, this is not necessary, since traces can be enabled at runtime using the
702  * log control tool and can be persistently configured. See @ref c_log_controlling.
703  **/
704 //--------------------------------------------------------------------------------------------------
705 static inline void le_log_EnableTrace
706 (
707  const le_log_TraceRef_t traceRef ///< [IN] Trace reference obtained from le_log_GetTraceRef().
708 )
709 {
710  *((bool*)traceRef) = true;
711 }
712 
713 
714 //--------------------------------------------------------------------------------------------------
715 /**
716  * Disables a trace.
717  *
718  * @note Normally, this is not necessary, since traces can be enabled at runtime using the
719  * log control tool and can be persistently configured. See @ref c_log_controlling.
720  **/
721 //--------------------------------------------------------------------------------------------------
722 static inline void le_log_DisableTrace
723 (
724  const le_log_TraceRef_t traceRef ///< [IN] Trace reference obtained from le_log_GetTraceRef()
725 )
726 {
727  *((bool*)traceRef) = false;
728 }
729 
730 
731 
732 #endif // LEGATO_LOG_INCLUDE_GUARD
static le_log_TraceRef_t le_log_GetTraceRef(const char *keywordPtr)
Definition: le_log.h:634
#define LE_SHARED
Definition: le_basics.h:240
le_result_t
Definition: le_basics.h:35
static void le_log_EnableTrace(const le_log_TraceRef_t traceRef)
Definition: le_log.h:706
static le_log_Level_t le_log_GetFilterLevel(void)
Definition: le_log.h:682
Warning. Possibly indicates a problem. Should be addressed.
Definition: le_log.h:378
le_log_Level_t
Definition: le_log.h:374
Debug message.
Definition: le_log.h:376
static void le_log_SetFilterLevel(le_log_Level_t level)
Definition: le_log.h:668
Definition: le_log.h:379
const char * _le_log_GetResultCodeString(le_result_t resultCode)
Function that does the real work of translating result codes. See LE_RESULT_TXT.
Definition: le_log.h:381
Informational message. Normally expected.
Definition: le_log.h:377
Emergency. A fatal error has occurred. A process is being terminated.
Definition: le_log.h:383
static bool le_log_IsTraceEnabled(const le_log_TraceRef_t traceRef)
Definition: le_log.h:650
static void le_log_DisableTrace(const le_log_TraceRef_t traceRef)
Definition: le_log.h:723