The logging API provides four main parts (basics, filtering, threading & blackbox).
More...
|
#define | LOG_TRACE (LOG_DEBUG + 1) |
|
#define | QB_LOG_MAX_LEN 512 |
|
#define | QB_LOG_STRERROR_MAX_LEN 128 |
|
#define | QB_ATTR_SECTION __verbose /* conforms to C ident. */ |
|
#define | QB_ATTR_SECTION_STR QB_PP_STRINGIFY(QB_ATTR_SECTION) |
|
#define | QB_ATTR_SECTION_START QB_PP_JOIN(__start_, QB_ATTR_SECTION) |
|
#define | QB_ATTR_SECTION_STOP QB_PP_JOIN(__stop_, QB_ATTR_SECTION) |
|
#define | QB_ATTR_SECTION_START_STR QB_PP_STRINGIFY(QB_ATTR_SECTION_START) |
|
#define | QB_ATTR_SECTION_STOP_STR QB_PP_STRINGIFY(QB_ATTR_SECTION_STOP) |
|
#define | QB_LOG_INIT_DATA(name) |
|
#define | QB_LOG_TAG_LIBQB_MSG_BIT 31 |
|
#define | QB_LOG_TAG_LIBQB_MSG (1 << QB_LOG_TAG_LIBQB_MSG_BIT) |
|
#define | qb_logt(priority, tags, fmt, args...) |
| This is the function to generate a log message if you want to manually add tags. More...
|
|
#define | qb_log(priority, fmt, args...) qb_logt(priority, 0, fmt, ##args) |
| This is the main function to generate a log message. More...
|
|
#define | QB_XC '\a' |
|
#define | QB_XS "\a" |
|
#define | qb_perror(priority, fmt, args...) |
| This is similar to perror except it goes into the logging system. More...
|
|
#define | qb_enter() qb_log(LOG_TRACE, "ENTERING %s()", __func__) |
|
#define | qb_leave() qb_log(LOG_TRACE, "LEAVING %s()", __func__) |
|
#define | QB_LOG_CTL2_I32(a) ((qb_log_ctl2_arg_t) { .i32 = (a) }) |
|
#define | QB_LOG_CTL2_S(a) ((qb_log_ctl2_arg_t) { .s = (a) }) |
|
|
struct qb_log_callsite | __attribute__ ((aligned(8))) |
|
void | qb_log_real_ (struct qb_log_callsite *cs,...) |
| Internal function: use qb_log() or qb_logt() More...
|
|
void | qb_log_real_va_ (struct qb_log_callsite *cs, va_list ap) |
|
void | qb_log_from_external_source (const char *function, const char *filename, const char *format, uint8_t priority, uint32_t lineno, uint32_t tags,...) __attribute__((format(printf |
| This function is to import logs from other code (like libraries) that provide a callback with their logs. More...
|
|
void struct qb_log_callsite * | qb_log_callsite_get (const char *function, const char *filename, const char *format, uint8_t priority, uint32_t lineno, uint32_t tags) |
| Get or create a callsite at the given position. More...
|
|
void | qb_log_from_external_source_va (const char *function, const char *filename, const char *format, uint8_t priority, uint32_t lineno, uint32_t tags, va_list ap) __attribute__((format(printf |
|
void | qb_log_init (const char *name, int32_t facility, uint8_t priority) |
| Init the logging system. More...
|
|
void | qb_log_fini (void) |
| Logging system finalization function. More...
|
|
int32_t | qb_log_callsites_register (struct qb_log_callsite *_start, struct qb_log_callsite *_stop) |
| If you are using dynamically loadable modules via dlopen() and you load them after qb_log_init() then after you load the module you will need to do the following to get the filters to work in that module: More...
|
|
void | qb_log_callsites_dump (void) |
| Dump the callsite info to stdout. More...
|
|
int32_t | qb_log_ctl (int32_t target, enum qb_log_conf conf_type, int32_t arg) |
| Main logging control function. More...
|
|
int32_t | qb_log_ctl2 (int32_t target, enum qb_log_conf conf_type, qb_log_ctl2_arg_t arg) |
| Extension of main logging control function accepting also strings. More...
|
|
int32_t | qb_log_filter_ctl (int32_t value, enum qb_log_filter_conf c, enum qb_log_filter_type type, const char *text, uint8_t low_priority) |
| This allows you modify the 'tags' and 'targets' callsite fields at runtime. More...
|
|
int32_t | qb_log_filter_ctl2 (int32_t value, enum qb_log_filter_conf c, enum qb_log_filter_type type, const char *text, uint8_t high_priority, uint8_t low_priority) |
| This extends qb_log_filter_ctl() by been able to provide a high_priority. More...
|
|
int32_t | qb_log_filter_fn_set (qb_log_filter_fn fn) |
| Instead of using the qb_log_filter_ctl() functions you can apply the filters manually by defining a callback and setting the targets field using qb_bit_set() and qb_bit_clear() like the following below: More...
|
|
void | qb_log_tags_stringify_fn_set (qb_log_tags_stringify_fn fn) |
| Set the callback to map the 'tags' bit map to a string. More...
|
|
void | qb_log_format_set (int32_t t, const char *format) |
| Set the format specifiers. More...
|
|
int32_t | qb_log_file_open (const char *filename) |
| Open a log file. More...
|
|
void | qb_log_file_close (int32_t t) |
| Close a log file and release is resources. More...
|
|
int32_t | qb_log_thread_priority_set (int32_t policy, int32_t priority) |
| When using threaded logging set the pthread policy and priority. More...
|
|
int32_t | qb_log_thread_start (void) |
| Start the logging pthread. More...
|
|
ssize_t | qb_log_blackbox_write_to_file (const char *filename) |
| Write the blackbox to file. More...
|
|
void | qb_log_blackbox_print_from_file (const char *filename) |
| Read the blackbox for file and print it out. More...
|
|
int32_t | qb_log_custom_open (qb_log_logger_fn log_fn, qb_log_close_fn close_fn, qb_log_reload_fn reload_fn, void *user_data) |
| Open a custom log target. More...
|
|
void | qb_log_custom_close (int32_t t) |
| Close a custom log target and release is resources. More...
|
|
void * | qb_log_target_user_data_get (int32_t t) |
| Retrieve the user data set by either qb_log_custom_open or qb_log_target_user_data_set. More...
|
|
int32_t | qb_log_target_user_data_set (int32_t t, void *user_data) |
| Associate user data with this log target. More...
|
|
void | qb_log_target_format (int32_t target, struct qb_log_callsite *cs, time_t timestamp, const char *formatted_message, char *output_buffer) |
| format the callsite and timestamp info according to the format set using qb_log_format_set() It is intended to be used from your custom logger function. More...
|
|
int32_t | qb_log_facility2int (const char *fname) |
| Convert string "auth" to equivalent number "LOG_AUTH" etc. More...
|
|
const char * | qb_log_facility2str (int32_t fnum) |
| Convert number "LOG_AUTH" to equivalent string "auth" etc. More...
|
|
The logging API provides four main parts (basics, filtering, threading & blackbox).
The idea behind this logging system is not to be prescriptive but to provide a set of tools to help the developer achieve what they want quickly and easily.
- Basic logging API.
- Call qb_log() to generate a log message. Then to write the message somewhere meaningful call qb_log_ctl() to configure the targets.
Simplest possible use:
* main() {
*
*
qb_log(LOG_WARNING,
"watch out");
*
* }
*
- Configuring log targets.
- A log target can be syslog, stderr, the blackbox, stdout, or a text file. By default only syslog is enabled.
To enable a target do the following:
syslog, stderr, the blackbox, and stdout are static (they don't need to be created, just enabled or disabled). However you can open multiple logfiles (QB_LOG_TARGET_MAX - QB_LOG_TARGET_STATIC_MAX). To do this, use the following code:
Once your targets are enabled/opened you can configure them as follows: Configure the size of blackbox
Make logging to file threaded:
To workaround your syslog daemon filtering all messages > LOG_INFO
* LOG_INFO - LOG_DEBUG);
*
To ensure all logs to file targets are fsync'ed (default QB_FALSE)
- Filtering messages.
- To have more power over what log messages go to which target you can apply filters to the targets. What happens is the desired callsites have the correct bit set. Then when the log message is generated it gets sent to the targets based on which bit is set in the callsite's "target" bitmap. Messages can be filtered based on the:
- filename + priority
- function name + priority
- format string + priority
So to make all logs from evil_function() go to stderr, do the following:
So to make all logs from totem* (with a priority <= LOG_INFO) go to stderr, do the following:
So to make all logs with the substring "ringbuffer" go to stderr, do the following:
- Thread safe non-blocking logging.
- Logging is only thread safe when threaded logging is in use. If you plan on logging from multiple threads, you must initialize libqb's logger thread and use qb_log_filter_ctl to set the QB_LOG_CONF_THREADED flag on all the logging targets in use.
To achieve non-blocking logging, so that any calls to write() or syslog() will not hold up your program, you can use threaded logging as well.
Threaded logging use:
* main() {
*
* daemonize();
*
*
*
qb_log(LOG_WARNING,
"watch out");
*
* }
*
- A blackbox for in-field diagnosis.
- This stores log messages in a ringbuffer so they can be written to file if the program crashes (you will need to catch SIGSEGV). These can then be easily printed out later.
- Note
- the blackbox is not enabled by default.
Blackbox usage:
*
* static void sigsegv_handler(int sig)
* {
* (void)signal (SIGSEGV, SIG_DFL);
* raise(SIGSEGV);
* }
*
* main() {
*
* signal(SIGSEGV, sigsegv_handler);
*
*
*
qb_log(LOG_WARNING,
"watch out");
*
* }
*
- Tagging messages.
- You can tag messages using the second argument to qb_logt() or by using qb_log_filter_ctl(). This can be used to add feature or sub-system information to the logs.
*
const char* my_tags_stringify(uint32_t
tags) {
* return "libqb";
* } else if (tags == 3) {
* return "three";
* } else {
* return "MAIN";
* }
* }
* main() {
*
*
* }
*
The code above will produce:
* [libqb] some message
* [three] info hello
* [MAIN ] info hello
*