mirror of
https://salsa.debian.org/ha-team/libqb
synced 2025-08-26 23:44:41 +00:00

The message-id parameter will enable systemd catalogs. To enable message-id's the libqb should be configured with the --enable-systemd-journal option. Co-authored-by: root <Aleksei Burlakov>
819 lines
24 KiB
C
819 lines
24 KiB
C
/*
|
|
* Copyright (c) 2017 Red Hat, Inc.
|
|
*
|
|
* All rights reserved.
|
|
*
|
|
* Author: Angus Salkeld <asalkeld@redhat.com>
|
|
* Jan Pokorny <jpokorny@redhat.com>
|
|
*
|
|
* libqb is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation, either version 2.1 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* libqb is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with libqb. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef QB_LOG_H_DEFINED
|
|
#define QB_LOG_H_DEFINED
|
|
|
|
/* *INDENT-OFF* */
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
/* *INDENT-ON* */
|
|
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <errno.h>
|
|
#include <syslog.h>
|
|
#include <string.h>
|
|
#include <qb/qbutil.h>
|
|
#include <qb/qbconfig.h>
|
|
|
|
/**
|
|
* @file qblog.h
|
|
* 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.
|
|
*
|
|
* @par 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:
|
|
* @code
|
|
* main() {
|
|
* qb_log_init("simple-log", LOG_DAEMON, LOG_INFO);
|
|
* // ...
|
|
* qb_log(LOG_WARNING, "watch out");
|
|
* // ...
|
|
* qb_log_fini();
|
|
* }
|
|
* @endcode
|
|
*
|
|
* @par Configuring log targets.
|
|
* A log target can be syslog, stderr, the blackbox, stdout, or a text file.
|
|
* By default, only syslog is enabled. While this is usual for daemons,
|
|
* it is rarely appropriate for ordinary programs, which should
|
|
* disable it when other targets (see below) are to be used:
|
|
* @code
|
|
* qb_log_ctl(B_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
|
|
* @endcode
|
|
*
|
|
* To enable a target do the following:
|
|
* @code
|
|
* qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
|
|
* @endcode
|
|
*
|
|
* 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 (falling within inclusive range @c QB_LOG_TARGET_DYNAMIC_START
|
|
* up to @c QB_LOG_TARGET_DYNAMIC_END). To do this, use the following code:
|
|
* @code
|
|
* mytarget = qb_log_file_open("/var/log/mylogfile");
|
|
* qb_log_ctl(mytarget, QB_LOG_CONF_ENABLED, QB_TRUE);
|
|
* @endcode
|
|
*
|
|
* Once your targets are enabled/opened, you can configure them as follows:
|
|
* Configure the size of blackbox:
|
|
* @code
|
|
* qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 1024*10);
|
|
* @endcode
|
|
*
|
|
* Make logging to file threaded:
|
|
* @code
|
|
* qb_log_ctl(mytarget, QB_LOG_CONF_THREADED, QB_TRUE);
|
|
* @endcode
|
|
*
|
|
* Sometimes, syslog daemons are (pre)configured to filter messages not
|
|
* exceeding a particular priority. When this happens to be the logging
|
|
* target, the designated priority of the message is passed along unchanged,
|
|
* possibly resulting in message loss. For messages up to @c LOG_DEBUG
|
|
* importance, this can be worked around by proportionally bumping the
|
|
* priorities to be passed to syslog (here, the step is such that
|
|
* @c LOG_DEBUG gets promoted to @c LOG_INFO):
|
|
* @code
|
|
* qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_PRIORITY_BUMP,
|
|
* LOG_INFO - LOG_DEBUG);
|
|
* @endcode
|
|
*
|
|
* To ensure all logs to file targets are fsync'ed (new messages expressly
|
|
* transferred to the storage device as they keep coming, otherwise defaults
|
|
* to @c QB_FALSE):
|
|
* @code
|
|
* qb_log_ctl(mytarget, QB_LOG_CONF_FILE_SYNC, QB_TRUE);
|
|
* @endcode
|
|
*
|
|
*
|
|
* @par 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:
|
|
* @code
|
|
* qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
|
|
* QB_LOG_FILTER_FUNCTION, "evil_function", LOG_TRACE);
|
|
* @endcode
|
|
*
|
|
* So to make all logs from totem* (with a priority <= LOG_INFO) go to stderr,
|
|
* do the following:
|
|
* @code
|
|
* qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
|
|
* QB_LOG_FILTER_FILE, "totem", LOG_INFO);
|
|
* @endcode
|
|
*
|
|
* So to make all logs with the substring "ringbuffer" go to stderr,
|
|
* do the following:
|
|
* @code
|
|
* qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
|
|
* QB_LOG_FILTER_FORMAT, "ringbuffer", LOG_TRACE);
|
|
* @endcode
|
|
*
|
|
* @par 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:
|
|
* @code
|
|
* main() {
|
|
* qb_log_init("simple-log", LOG_DAEMON, LOG_INFO);
|
|
* qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_THREADED, QB_TRUE);
|
|
* // ...
|
|
* daemonize();
|
|
* // call this after you fork()
|
|
* qb_log_thread_start();
|
|
* // ...
|
|
* qb_log(LOG_WARNING, "watch out");
|
|
* // ...
|
|
* qb_log_fini();
|
|
* }
|
|
* @endcode
|
|
*
|
|
* @par 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:
|
|
* @code
|
|
*
|
|
* static void sigsegv_handler(int sig)
|
|
* {
|
|
* (void)signal (SIGSEGV, SIG_DFL);
|
|
* qb_log_blackbox_write_to_file("simple-log.fdata");
|
|
* qb_log_fini();
|
|
* raise(SIGSEGV);
|
|
* }
|
|
*
|
|
* main() {
|
|
*
|
|
* signal(SIGSEGV, sigsegv_handler);
|
|
*
|
|
* qb_log_init("simple-log", LOG_DAEMON, LOG_INFO);
|
|
* qb_log_filter_ctl(QB_LOG_BLACKBOX, QB_LOG_FILTER_ADD,
|
|
* QB_LOG_FILTER_FILE, "*", LOG_DEBUG);
|
|
* qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 1024*10);
|
|
* qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
|
|
* // ...
|
|
* qb_log(LOG_WARNING, "watch out");
|
|
* // ...
|
|
* qb_log_fini();
|
|
* }
|
|
* @endcode
|
|
*
|
|
* @par 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.
|
|
*
|
|
* @code
|
|
* const char* my_tags_stringify(uint32_t tags) {
|
|
* if (qb_bit_is_set(tags, QB_LOG_TAG_LIBQB_MSG_BIT) {
|
|
* return "libqb";
|
|
* } else if (tags == 3) {
|
|
* return "three";
|
|
* } else {
|
|
* return "MAIN";
|
|
* }
|
|
* }
|
|
* main() {
|
|
* // ...
|
|
* qb_log_tags_stringify_fn_set(my_tags_stringify);
|
|
* qb_log_format_set(QB_LOG_STDERR, "[%5g] %p %b");
|
|
* // ...
|
|
* qb_logt(LOG_INFO, 3, "hello");
|
|
* qb_logt(LOG_INFO, 0, "hello");
|
|
* }
|
|
* @endcode
|
|
* The code above will produce:
|
|
* @code
|
|
* [libqb] some message
|
|
* [three] info hello
|
|
* [MAIN ] info hello
|
|
* @endcode
|
|
*
|
|
* @example simplelog.c
|
|
*/
|
|
|
|
#undef LOG_TRACE
|
|
#define LOG_TRACE (LOG_DEBUG + 1)
|
|
|
|
#define QB_LOG_MAX_LEN 512
|
|
#define QB_LOG_ABSOLUTE_MAX_LEN 4096
|
|
#define QB_LOG_STRERROR_MAX_LEN 128
|
|
|
|
typedef const char *(*qb_log_tags_stringify_fn)(uint32_t tags);
|
|
|
|
/**
|
|
* An instance of this structure is created for each log message
|
|
* with the message-id
|
|
*/
|
|
struct qb_log_callsite {
|
|
const char *function;
|
|
const char *filename;
|
|
const char *format;
|
|
uint8_t priority;
|
|
uint32_t lineno;
|
|
uint32_t targets;
|
|
uint32_t tags;
|
|
const char *message_id;
|
|
} __attribute__((aligned(8)));
|
|
|
|
typedef void (*qb_log_filter_fn)(struct qb_log_callsite * cs);
|
|
|
|
#define QB_LOG_INIT_DATA(name)
|
|
|
|
/**
|
|
* Internal function: use qb_log() or qb_logt()
|
|
*/
|
|
void qb_log_real_(struct qb_log_callsite *cs, ...);
|
|
void qb_log_real_va_(struct qb_log_callsite *cs, va_list ap);
|
|
|
|
#define QB_LOG_TAG_LIBQB_MSG_BIT 31
|
|
#define QB_LOG_TAG_LIBQB_MSG (1U << QB_LOG_TAG_LIBQB_MSG_BIT)
|
|
|
|
/**
|
|
* This function is to import logs from other code (like libraries)
|
|
* that provide a callback with their logs.
|
|
*
|
|
* @note the performance of this will not impress you, as
|
|
* the filtering is done on each log message, not
|
|
* beforehand. So try doing basic pre-filtering.
|
|
*
|
|
* @param function originating function name
|
|
* @param filename originating filename
|
|
* @param format format string
|
|
* @param priority this takes syslog priorities.
|
|
* @param lineno file line number
|
|
* @param tags this is a uint32_t that you can use with
|
|
* qb_log_tags_stringify_fn_set() to "tag" a log message
|
|
* with a feature or sub-system then you can use "%g"
|
|
* in the format specifer to print it out.
|
|
*/
|
|
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, 3, 7)));
|
|
|
|
/**
|
|
* Get or create a callsite at the given position.
|
|
*
|
|
* The result can then be passed into qb_log_real_()
|
|
*
|
|
* @param function originating function name
|
|
* @param filename originating filename
|
|
* @param format format string
|
|
* @param priority this takes syslog priorities.
|
|
* @param lineno file line number
|
|
* @param tags the tag
|
|
*/
|
|
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.
|
|
* The same that qb_log_callsite_get but with the
|
|
* message_id parameter.
|
|
*
|
|
* The result can then be passed into qb_log_real_()
|
|
*
|
|
* @param message_id in the systemd catalog or NULL
|
|
* @param function originating function name
|
|
* @param filename originating filename
|
|
* @param format format string
|
|
* @param priority this takes syslog priorities.
|
|
* @param lineno file line number
|
|
* @param tags the tag
|
|
*/
|
|
struct qb_log_callsite* qb_log_callsite_get2(const char *message_id,
|
|
const char *function,
|
|
const char *filename,
|
|
const char *format,
|
|
uint8_t priority,
|
|
uint32_t lineno,
|
|
uint32_t tags);
|
|
|
|
void qb_log_from_external_source_va2(const char *message_id,
|
|
const char *function,
|
|
const char *filename,
|
|
const char *format,
|
|
uint8_t priority,
|
|
uint32_t lineno,
|
|
uint32_t tags,
|
|
va_list ap)
|
|
__attribute__ ((format (printf, 4, 0)));
|
|
|
|
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, 3, 0)));
|
|
|
|
/**
|
|
* This is the function to generate a log message if you want to
|
|
* manually add tags.
|
|
*
|
|
* @param message_id in the systemd catalog or NULL
|
|
* @param priority this takes syslog priorities.
|
|
* @param tags this is a uint32_t that you can use with
|
|
* qb_log_tags_stringify_fn_set() to "tag" a log message
|
|
* with a feature or sub-system then you can use "%g"
|
|
* in the format specifer to print it out.
|
|
* @param fmt usual printf style format specifiers
|
|
* @param args usual printf style args
|
|
*/
|
|
#define qb_logt2(message_id, priority, tags, fmt, args...) do { \
|
|
struct qb_log_callsite* descriptor_pt = \
|
|
qb_log_callsite_get2(message_id, __func__, __FILE__, fmt, \
|
|
priority, __LINE__, tags); \
|
|
qb_log_real_(descriptor_pt, ##args); \
|
|
} while(0)
|
|
|
|
/**
|
|
* This is the function to generate a log message if you want to
|
|
* manually add tags.
|
|
*
|
|
* @param priority this takes syslog priorities.
|
|
* @param tags this is a uint32_t that you can use with
|
|
* qb_log_tags_stringify_fn_set() to "tag" a log message
|
|
* with a feature or sub-system then you can use "%g"
|
|
* in the format specifer to print it out.
|
|
* @param fmt usual printf style format specifiers
|
|
* @param args usual printf style args
|
|
*/
|
|
#define qb_logt(priority, tags, fmt, args...) qb_logt2(NULL, priority, tags, fmt, ##args)
|
|
|
|
|
|
/**
|
|
* This is the main function to generate a log message.
|
|
*
|
|
* @param message_id in the systemd catalog or NULL
|
|
* @param priority this takes syslog priorities.
|
|
* @param fmt usual printf style format specifiers
|
|
* @param args usual printf style args
|
|
*/
|
|
#define qb_log2(message_id, priority, fmt, args...) qb_logt2(message_id, priority, 0, fmt, ##args)
|
|
|
|
/**
|
|
* This is the main function to generate a log message.
|
|
*
|
|
* @param priority this takes syslog priorities.
|
|
* @param fmt usual printf style format specifiers
|
|
* @param args usual printf style args
|
|
*/
|
|
#define qb_log(priority, fmt, args...) qb_logt(priority, 0, fmt, ##args)
|
|
|
|
/* Define the character used to mark the beginning of "extended" information;
|
|
* a string equivalent is also defined so clients can use it like:
|
|
* qb_log(level, "blah blah "QB_XS" yada yada", __func__);
|
|
*/
|
|
#define QB_XC '\a'
|
|
#define QB_XS "\a"
|
|
|
|
/**
|
|
* This is similar to perror except it goes into the logging system.
|
|
*
|
|
* @param priority this takes syslog priorities.
|
|
* @param fmt usual printf style format specifiers
|
|
* @param args usual printf style args
|
|
*
|
|
* @note Because qb_perror() adds the system error message and error number onto
|
|
* the end of the given fmt, that information will become extended
|
|
* information if QB_XS is used inside fmt and will not show up in any
|
|
* logs that strip extended information.
|
|
*/
|
|
#ifndef S_SPLINT_S
|
|
#define qb_perror(priority, fmt, args...) do { \
|
|
char _perr_buf_[QB_LOG_STRERROR_MAX_LEN]; \
|
|
const char *_perr_str_ = qb_strerror_r(errno, _perr_buf_, sizeof(_perr_buf_)); \
|
|
qb_logt(priority, 0, fmt ": %s (%d)", ##args, _perr_str_, errno); \
|
|
} while(0)
|
|
#else
|
|
#define qb_perror
|
|
#endif
|
|
|
|
#define qb_enter() qb_log(LOG_TRACE, "ENTERING %s()", __func__)
|
|
#define qb_leave() qb_log(LOG_TRACE, "LEAVING %s()", __func__)
|
|
|
|
/*
|
|
* Note that QB_LOG_TARGET_{STATIC_,}MAX are sentinel indexes
|
|
* as non-inclusive higher bounds of the respective categories
|
|
* (static and all the log targets) and also denote the number
|
|
* of (reserved) items in the category. Both are possibly subject
|
|
* to change, so you should always refer to them using
|
|
* these defined values.
|
|
* Similarly, there are QB_LOG_TARGET_{STATIC_,DYNAMIC_,}START
|
|
* and QB_LOG_TARGET_{STATIC_,DYNAMIC_,}END values, but these
|
|
* are inclusive lower and higher bounds, respectively.
|
|
*/
|
|
enum qb_log_target_slot {
|
|
QB_LOG_TARGET_START,
|
|
|
|
/* static */
|
|
QB_LOG_TARGET_STATIC_START = QB_LOG_TARGET_START,
|
|
QB_LOG_SYSLOG = QB_LOG_TARGET_STATIC_START,
|
|
QB_LOG_STDERR,
|
|
QB_LOG_BLACKBOX,
|
|
QB_LOG_STDOUT,
|
|
QB_LOG_TARGET_STATIC_MAX,
|
|
QB_LOG_TARGET_STATIC_END = QB_LOG_TARGET_STATIC_MAX - 1,
|
|
|
|
/* dynamic */
|
|
QB_LOG_TARGET_DYNAMIC_START = QB_LOG_TARGET_STATIC_MAX,
|
|
|
|
QB_LOG_TARGET_MAX = 32,
|
|
QB_LOG_TARGET_DYNAMIC_END = QB_LOG_TARGET_MAX - 1,
|
|
QB_LOG_TARGET_END = QB_LOG_TARGET_DYNAMIC_END,
|
|
};
|
|
|
|
enum qb_log_target_state {
|
|
QB_LOG_STATE_UNUSED = 1,
|
|
QB_LOG_STATE_DISABLED = 2,
|
|
QB_LOG_STATE_ENABLED = 3,
|
|
};
|
|
|
|
enum qb_log_conf {
|
|
QB_LOG_CONF_ENABLED,
|
|
QB_LOG_CONF_FACILITY,
|
|
QB_LOG_CONF_DEBUG,
|
|
QB_LOG_CONF_SIZE,
|
|
QB_LOG_CONF_THREADED,
|
|
QB_LOG_CONF_PRIORITY_BUMP,
|
|
QB_LOG_CONF_STATE_GET,
|
|
QB_LOG_CONF_FILE_SYNC,
|
|
QB_LOG_CONF_EXTENDED,
|
|
QB_LOG_CONF_IDENT,
|
|
QB_LOG_CONF_MAX_LINE_LEN,
|
|
QB_LOG_CONF_ELLIPSIS,
|
|
QB_LOG_CONF_USE_JOURNAL,
|
|
};
|
|
|
|
enum qb_log_filter_type {
|
|
QB_LOG_FILTER_FILE,
|
|
QB_LOG_FILTER_FUNCTION,
|
|
QB_LOG_FILTER_FORMAT,
|
|
QB_LOG_FILTER_FILE_REGEX,
|
|
QB_LOG_FILTER_FUNCTION_REGEX,
|
|
QB_LOG_FILTER_FORMAT_REGEX,
|
|
};
|
|
|
|
enum qb_log_filter_conf {
|
|
QB_LOG_FILTER_ADD,
|
|
QB_LOG_FILTER_REMOVE,
|
|
QB_LOG_FILTER_CLEAR_ALL,
|
|
QB_LOG_TAG_SET,
|
|
QB_LOG_TAG_CLEAR,
|
|
QB_LOG_TAG_CLEAR_ALL,
|
|
};
|
|
|
|
typedef void (*qb_log_logger_fn)(int32_t t,
|
|
struct qb_log_callsite *cs,
|
|
struct timespec *timestamp,
|
|
const char *msg);
|
|
typedef void (*qb_log_vlogger_fn)(int32_t t,
|
|
struct qb_log_callsite *cs,
|
|
struct timespec *timestamp,
|
|
va_list ap);
|
|
|
|
typedef void (*qb_log_close_fn)(int32_t t);
|
|
typedef void (*qb_log_reload_fn)(int32_t t);
|
|
|
|
/**
|
|
* Init the logging system.
|
|
*
|
|
* @param name will be passed into openlog()
|
|
* @param facility default for all new targets.
|
|
* @param priority a basic filter with this priority will be added.
|
|
*/
|
|
void qb_log_init(const char *name,
|
|
int32_t facility,
|
|
uint8_t priority);
|
|
|
|
/**
|
|
* Logging system finalization function.
|
|
*
|
|
* It releases any shared memory.
|
|
* Stops the logging thread if running.
|
|
* Flushes the last messages to their destinations.
|
|
*/
|
|
void qb_log_fini(void);
|
|
|
|
/**
|
|
* 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:
|
|
* @code
|
|
* _start = dlsym (dl_handle, QB_ATTR_SECTION_START_STR);
|
|
* _stop = dlsym (dl_handle, QB_ATTR_SECTION_STOP_STR);
|
|
* qb_log_callsites_register(_start, _stop);
|
|
* @endcode
|
|
*/
|
|
int32_t qb_log_callsites_register(struct qb_log_callsite *_start, struct qb_log_callsite *_stop);
|
|
|
|
/**
|
|
* Dump the callsite info to stdout.
|
|
*/
|
|
void qb_log_callsites_dump(void);
|
|
|
|
/**
|
|
* Main logging control function.
|
|
*
|
|
* @param target QB_LOG_SYSLOG, QB_LOG_STDERR or result from qb_log_file_open()
|
|
* @param conf_type configuration directive ("what to configure") that accepts
|
|
* @c int32_t argument determining the new value unless ignored
|
|
* for particular directive altogether
|
|
* (incompatible directives: QB_LOG_CONF_IDENT)
|
|
* @param arg the new value for a state-changing configuration directive,
|
|
* ignored otherwise
|
|
* @see qb_log_conf
|
|
*
|
|
* @retval -errno on error
|
|
* @retval 0 on success
|
|
* @retval qb_log_target_state for QB_LOG_CONF_STATE_GET
|
|
*/
|
|
int32_t qb_log_ctl(int32_t target, enum qb_log_conf conf_type, int32_t arg);
|
|
|
|
typedef union {
|
|
int32_t i32;
|
|
const char *s;
|
|
} qb_log_ctl2_arg_t;
|
|
|
|
/**
|
|
* Extension of main logging control function accepting also strings.
|
|
*
|
|
* @param target QB_LOG_SYSLOG, QB_LOG_STDERR or result from qb_log_file_open()
|
|
* @param conf_type configuration directive ("what to configure") that accepts
|
|
* either @c int32_t or a null-terminated string argument
|
|
* determining the new value unless ignored for particular directive
|
|
* (compatible directives: those valid for qb_log_ctl
|
|
* + QB_LOG_CONF_IDENT)
|
|
* @param arg the new value for a state-changing configuration directive,
|
|
* ignored otherwise; for QB_LOG_CONF_IDENT, 's' member as new
|
|
* identifier to openlog(), for all qb_log_ctl-compatible ones,
|
|
* 'i32' member is assumed (although a preferred way is to use
|
|
* that original function directly as it allows for more type safety)
|
|
* @see qb_log_ctl
|
|
*
|
|
* @note You can use @ref QB_LOG_CTL2_I32 and @ref QB_LOG_CTL2_S macros
|
|
* for a convenient on-the-fly construction of the object
|
|
* to be passed as an @p arg argument.
|
|
*/
|
|
int32_t qb_log_ctl2(int32_t target, enum qb_log_conf conf_type,
|
|
qb_log_ctl2_arg_t arg);
|
|
|
|
# ifndef S_SPLINT_S
|
|
#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) })
|
|
#else
|
|
#define QB_LOG_CTL2_I32(a) ((qb_log_ctl2_arg_t)(a))
|
|
#define QB_LOG_CTL2_S(a) ((qb_log_ctl2_arg_t)(a))
|
|
#endif
|
|
|
|
/**
|
|
* This allows you modify the 'tags' and 'targets' callsite fields at runtime.
|
|
*/
|
|
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 extends qb_log_filter_ctl() by been able to provide a high_priority.
|
|
*/
|
|
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);
|
|
|
|
|
|
/**
|
|
* 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:
|
|
* @code
|
|
* static void
|
|
* m_filter(struct qb_log_callsite *cs)
|
|
* {
|
|
* if ((cs->priority >= LOG_ALERT &&
|
|
* cs->priority <= LOG_DEBUG) &&
|
|
* strcmp(cs->filename, "my_c_file.c") == 0) {
|
|
* qb_bit_set(cs->targets, QB_LOG_SYSLOG);
|
|
* } else {
|
|
* qb_bit_clear(cs->targets, QB_LOG_SYSLOG);
|
|
* }
|
|
* }
|
|
* @endcode
|
|
*/
|
|
int32_t qb_log_filter_fn_set(qb_log_filter_fn fn);
|
|
|
|
/**
|
|
* Set the callback to map the 'tags' bit map to a string.
|
|
*/
|
|
void qb_log_tags_stringify_fn_set(qb_log_tags_stringify_fn fn);
|
|
|
|
|
|
/**
|
|
*This is a Feature Test macro so that calling applications know that
|
|
* millisecond timestamps are implemented. Because %T a string in
|
|
* function call with an indirect effect, there is no easy test for it
|
|
* beyond the library version (which is a very blunt instrument)
|
|
*/
|
|
#define QB_FEATURE_LOG_HIRES_TIMESTAMPS 1
|
|
|
|
/**
|
|
* Set the format specifiers.
|
|
*
|
|
* \%n FUNCTION NAME
|
|
*
|
|
* \%f FILENAME
|
|
*
|
|
* \%l FILELINE
|
|
*
|
|
* \%p PRIORITY
|
|
*
|
|
* \%t TIMESTAMP
|
|
*
|
|
* \%T TIMESTAMP with milliseconds
|
|
*
|
|
* \%b BUFFER
|
|
*
|
|
* \%g TAGS
|
|
*
|
|
* \%N name (passed into qb_log_init)
|
|
*
|
|
* \%P PID
|
|
*
|
|
* \%H hostname
|
|
*
|
|
* Any number between % and character specify field length to pad or chop.
|
|
*
|
|
* @note Some of the fields are immediately evaluated and remembered
|
|
* for performance reasons, so whenlog messages carry PIDs (not the default)
|
|
* this function needs to be reinvoked following @c fork
|
|
* (@c clone) in the respective children. When already linking
|
|
* with @c libpthread, @c pthread_atfork callback registration
|
|
* could be useful.
|
|
*/
|
|
void qb_log_format_set(int32_t t, const char* format);
|
|
|
|
/**
|
|
* Open a log file.
|
|
*
|
|
* @retval -errno on error
|
|
* @retval value in inclusive range QB_LOG_TARGET_DYNAMIC_START
|
|
* to QB_LOG_TARGET_DYNAMIC_END
|
|
* (to be passed into other qb_log_* functions)
|
|
*/
|
|
int32_t qb_log_file_open(const char *filename);
|
|
|
|
/**
|
|
* Close a log file and release its resources.
|
|
*/
|
|
void qb_log_file_close(int32_t t);
|
|
|
|
/**
|
|
* Open a new log file for an existing target
|
|
* @param t target
|
|
* @param filename may be NULL to use existing file name
|
|
*
|
|
* @retval -errno on error
|
|
*
|
|
*/
|
|
int32_t qb_log_file_reopen(int32_t t, const char *filename);
|
|
|
|
/**
|
|
* When using threaded logging set the pthread policy and priority.
|
|
*
|
|
* @retval -errno on error
|
|
* @retval 0 success
|
|
*/
|
|
int32_t qb_log_thread_priority_set(int32_t policy, int32_t priority);
|
|
|
|
/**
|
|
* Start the logging pthread.
|
|
*/
|
|
int32_t qb_log_thread_start(void);
|
|
|
|
/**
|
|
* Write the blackbox to file.
|
|
*/
|
|
ssize_t qb_log_blackbox_write_to_file(const char *filename);
|
|
|
|
/**
|
|
* Read the blackbox for file and print it out.
|
|
*/
|
|
int qb_log_blackbox_print_from_file(const char* filename);
|
|
|
|
/**
|
|
* Open a custom log target.
|
|
*
|
|
* @retval -errno on error
|
|
* @retval value in inclusive range QB_LOG_TARGET_DYNAMIC_START
|
|
* to QB_LOG_TARGET_DYNAMIC_END
|
|
* (to be passed into other qb_log_* functions)
|
|
*/
|
|
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);
|
|
|
|
/**
|
|
* Close a custom log target and release its resources.
|
|
*/
|
|
void qb_log_custom_close(int32_t t);
|
|
|
|
/**
|
|
* Retrieve the user data set by either qb_log_custom_open or
|
|
* qb_log_target_user_data_set.
|
|
*/
|
|
void *qb_log_target_user_data_get(int32_t t);
|
|
|
|
/**
|
|
* Associate user data with this log target.
|
|
* @note only use this with custom targets
|
|
*/
|
|
int32_t qb_log_target_user_data_set(int32_t t, void *user_data);
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
void qb_log_target_format(int32_t target,
|
|
struct qb_log_callsite *cs,
|
|
struct timespec *timestamp,
|
|
const char* formatted_message,
|
|
char *output_buffer);
|
|
|
|
/**
|
|
* Convert string "auth" to equivalent number "LOG_AUTH" etc.
|
|
*/
|
|
int32_t qb_log_facility2int(const char *fname);
|
|
|
|
/**
|
|
* Convert number "LOG_AUTH" to equivalent string "auth" etc.
|
|
*/
|
|
const char * qb_log_facility2str(int32_t fnum);
|
|
|
|
/* *INDENT-OFF* */
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif /* __cplusplus */
|
|
/* *INDENT-ON* */
|
|
#endif /* QB_LOG_H_DEFINED */
|