mirror of
https://salsa.debian.org/ha-team/libqb
synced 2026-08-08 20:07:21 +00:00
Add logging infrastructure.
Signed-off-by: Angus Salkeld <asalkeld@redhat.com>
This commit is contained in:
parent
ea704d5821
commit
e910f8bc18
@ -26,7 +26,7 @@ inc_dir = $(top_srcdir)/include/qb
|
||||
dependant_headers = $(wildcard $(inc_dir)/qb*.h)
|
||||
dist_man_MANS = man3/qbipcc.h.3 man3/qbipcs.h.3 man3/qbatomic.h.3 \
|
||||
man3/qbhdb.h.3 man3/qbipc_common.h.3 man3/qblist.h.3 \
|
||||
man3/qbloop.h.3 man3/qbutil.h.3 man3/qbarray.h.3
|
||||
man3/qbloop.h.3 man3/qbutil.h.3 man3/qbarray.h.3 man3/qblog.h
|
||||
|
||||
|
||||
$(dist_man_MANS): man.dox $(dependant_headers)
|
||||
|
||||
@ -51,6 +51,12 @@
|
||||
* @see qbloop.h
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page qb_log_overview Logging
|
||||
* @copydoc qblog.h
|
||||
* @see qblog.h
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page qb_ipc_overview IPC Overview
|
||||
*
|
||||
|
||||
@ -47,6 +47,16 @@ extern "C" {
|
||||
#define QB_FALSE 0
|
||||
#define QB_TRUE (!QB_FALSE)
|
||||
|
||||
/*
|
||||
* bit manipulation
|
||||
*/
|
||||
#define qb_bit_value(bit) (1 << (bit))
|
||||
#define qb_bit_set(barray, bit) (barray |= qb_bit_value(bit))
|
||||
#define qb_bit_clear(barray, bit) (barray &= ~(qb_bit_value(bit)))
|
||||
#define qb_bit_is_set(barray, bit) (barray & qb_bit_value(bit))
|
||||
#define qb_bit_is_clear(barray, bit) (!(barray & qb_bit_value(bit)))
|
||||
|
||||
|
||||
/*
|
||||
* handy time based converters.
|
||||
*/
|
||||
|
||||
113
include/qb/qblog.h
Normal file
113
include/qb/qblog.h
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Red Hat, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Author: Angus Salkeld <asalkeld@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
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
|
||||
/**
|
||||
* @file qblog.h
|
||||
* This is a the logging API.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* An instance of this structure is created in a special
|
||||
* ELF section at every dynamic debug callsite. At runtime,
|
||||
* the special section is treated as an array of these.
|
||||
*/
|
||||
struct qb_log_callsite {
|
||||
const char *function;
|
||||
const char *filename;
|
||||
const char *format;
|
||||
uint8_t priority;
|
||||
uint32_t lineno;
|
||||
uint32_t tags;
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
|
||||
typedef struct qb_log_filter qb_log_filter_t;
|
||||
|
||||
typedef void (*qb_log_logger_fn)(struct qb_log_callsite *cs,
|
||||
const char *msg);
|
||||
|
||||
/* will be assigned by ld linker magic */
|
||||
extern struct qb_log_callsite __start___verbose[];
|
||||
extern struct qb_log_callsite __stop___verbose[];
|
||||
|
||||
/**
|
||||
* Internal function use qb_log()
|
||||
*/
|
||||
void qb_log_real_(struct qb_log_callsite *cs,
|
||||
int32_t error_number, ...);
|
||||
|
||||
/**
|
||||
* 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...) do { \
|
||||
static struct qb_log_callsite descriptor \
|
||||
__attribute__((section("__verbose"), aligned(8))) = \
|
||||
{ __func__, __FILE__, fmt, priority, __LINE__, 0 }; \
|
||||
qb_log_real_(&descriptor, 0, ##args); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* Create a filter to tag the callsites.
|
||||
*/
|
||||
qb_log_filter_t* qb_log_filter_create(void);
|
||||
|
||||
/**
|
||||
* destroy a filter.
|
||||
*/
|
||||
void qb_log_filter_destroy(struct qb_log_filter* flt);
|
||||
|
||||
/**
|
||||
* Set the priority on the filter
|
||||
*/
|
||||
int32_t qb_log_filter_priority_set(qb_log_filter_t* flt, uint8_t priority);
|
||||
|
||||
/**
|
||||
* add a chunk of code to a filter.
|
||||
*/
|
||||
void qb_log_filter_file_add(struct qb_log_filter* flt,
|
||||
const char* filename,
|
||||
int32_t start, int32_t end);
|
||||
|
||||
/**
|
||||
* tag the callsites defined by the filter.
|
||||
*/
|
||||
void qb_log_tag(struct qb_log_filter* flt, int32_t is_set, int32_t tag_bit);
|
||||
|
||||
/**
|
||||
* set your log handling function.
|
||||
*/
|
||||
void qb_log_handler_set(qb_log_logger_fn logger_fn);
|
||||
|
||||
|
||||
#endif /* QB_LOG_H_DEFINED */
|
||||
@ -40,7 +40,8 @@ libqb_la_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
|
||||
libqb_la_LDFLAGS = -version-info 4:1:4
|
||||
source_to_lint = util.c hdb.c ringbuffer.c ringbuffer_helper.c array.c \
|
||||
loop.c loop_poll.c loop_job.c \
|
||||
ipcc.c ipcs.c ipc_posix_mq.c ipc_sysv_mq.c ipc_shm.c ipc_us.c
|
||||
ipcc.c ipcs.c ipc_posix_mq.c ipc_sysv_mq.c ipc_shm.c ipc_us.c \
|
||||
log.c
|
||||
libqb_la_SOURCES = $(source_to_lint)
|
||||
if USE_TIMERFD
|
||||
else
|
||||
|
||||
159
lib/log.c
Normal file
159
lib/log.c
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Red Hat, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Author: Angus Salkeld <asalkeld@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/>.
|
||||
*/
|
||||
#include <config.h>
|
||||
|
||||
#include "os_base.h"
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <qb/qbdefs.h>
|
||||
#include <qb/qblist.h>
|
||||
#include <qb/qblog.h>
|
||||
|
||||
struct qb_log_filter_file {
|
||||
char *filename;
|
||||
int32_t start;
|
||||
int32_t end;
|
||||
struct qb_list_head list;
|
||||
};
|
||||
|
||||
struct qb_log_filter {
|
||||
uint8_t priority;
|
||||
struct qb_list_head files_head;
|
||||
};
|
||||
|
||||
struct qb_log_destination {
|
||||
qb_log_logger_fn logger;
|
||||
};
|
||||
|
||||
#define COMBINE_BUFFER_SIZE 256
|
||||
static struct qb_log_destination destination;
|
||||
|
||||
|
||||
void qb_log_real_(struct qb_log_callsite *cs,
|
||||
int32_t error_number, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[COMBINE_BUFFER_SIZE];
|
||||
size_t len;
|
||||
static int32_t in_logger = 0;
|
||||
|
||||
if (destination.logger == NULL) {
|
||||
return;
|
||||
}
|
||||
if (in_logger) {
|
||||
return;
|
||||
}
|
||||
in_logger = 1;
|
||||
|
||||
va_start(ap, error_number);
|
||||
len = vsnprintf(buf, COMBINE_BUFFER_SIZE, cs->format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (buf[len - 1] == '\n') {
|
||||
buf[len - 1] = '\0';
|
||||
len -= 1;
|
||||
}
|
||||
|
||||
destination.logger(cs, buf);
|
||||
in_logger = 0;
|
||||
}
|
||||
|
||||
qb_log_filter_t* qb_log_filter_create(void)
|
||||
{
|
||||
struct qb_log_filter *flt = calloc(1, sizeof(struct qb_log_filter));
|
||||
qb_list_init(&flt->files_head);
|
||||
flt->priority = LOG_INFO;
|
||||
return flt;
|
||||
}
|
||||
|
||||
void qb_log_filter_destroy(struct qb_log_filter* flt)
|
||||
{
|
||||
struct qb_log_filter_file *ff;
|
||||
struct qb_list_head *item;
|
||||
struct qb_list_head *next;
|
||||
|
||||
qb_list_for_each_safe(item, next, &flt->files_head) {
|
||||
ff = qb_list_entry(item, struct qb_log_filter_file, list);
|
||||
qb_list_del(item);
|
||||
free(ff);
|
||||
}
|
||||
|
||||
free(flt);
|
||||
}
|
||||
|
||||
int32_t qb_log_filter_priority_set(struct qb_log_filter* flt, uint8_t priority)
|
||||
{
|
||||
flt->priority = priority;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qb_log_filter_file_add(struct qb_log_filter* flt,
|
||||
const char* filename,
|
||||
int32_t start, int32_t end)
|
||||
{
|
||||
struct qb_log_filter_file *ff = calloc(1, sizeof(struct qb_log_filter_file));
|
||||
qb_list_init(&ff->list);
|
||||
ff->filename = (char*)filename;
|
||||
ff->start = start;
|
||||
ff->end = end;
|
||||
qb_list_add(&ff->list, &flt->files_head);
|
||||
}
|
||||
|
||||
void qb_log_tag(struct qb_log_filter* flt, int32_t is_set, int32_t tag_bit)
|
||||
{
|
||||
struct qb_log_callsite *cs;
|
||||
struct qb_log_filter_file *ff;
|
||||
int32_t match;
|
||||
|
||||
for (cs = __start___verbose; cs < __stop___verbose; cs++) {
|
||||
if (cs->priority > flt->priority)
|
||||
continue;
|
||||
match = QB_FALSE;
|
||||
qb_list_for_each_entry(ff, &flt->files_head, list) {
|
||||
if (ff->start <= cs->lineno &&
|
||||
ff->end >= cs->lineno &&
|
||||
strcmp(ff->filename, cs->filename) == 0) {
|
||||
match = QB_TRUE;
|
||||
}
|
||||
}
|
||||
if (match || qb_list_empty(&flt->files_head)) {
|
||||
if (is_set) {
|
||||
qb_bit_set(cs->tags, tag_bit);
|
||||
} else {
|
||||
qb_bit_clear(cs->tags, tag_bit);
|
||||
}
|
||||
#if 0
|
||||
printf("matched: %-12s %20s:%u fmt:<%d>%s\n",
|
||||
cs->function, cs->filename, cs->lineno,
|
||||
cs->priority, cs->format);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void qb_log_handler_set(qb_log_logger_fn logger_fn)
|
||||
{
|
||||
destination.logger = NULL;
|
||||
qb_log(LOG_DEBUG, " ");
|
||||
destination.logger = logger_fn;
|
||||
}
|
||||
|
||||
1
tests/.gitignore
vendored
1
tests/.gitignore
vendored
@ -8,3 +8,4 @@ bms
|
||||
rbreader
|
||||
rbwriter
|
||||
loop
|
||||
simple-log
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
# along with libqb. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
noinst_PROGRAMS = bmc bmcpt bms rbwriter rbreader loop
|
||||
noinst_PROGRAMS = bmc bmcpt bms rbwriter rbreader loop simple-log
|
||||
|
||||
bmc_SOURCES = bmc.c $(top_builddir)/include/qb/qbipcc.h
|
||||
bmc_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
|
||||
@ -44,6 +44,10 @@ loop_SOURCES = loop.c $(top_builddir)/include/qb/qbloop.h
|
||||
loop_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
|
||||
loop_LDADD = -lrt $(top_builddir)/lib/libqb.la
|
||||
|
||||
simple_log_SOURCES = simple-log.c $(top_builddir)/include/qb/qblog.h
|
||||
simple_log_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
|
||||
simple_log_LDADD = -lrt $(top_builddir)/lib/libqb.la
|
||||
|
||||
|
||||
if HAVE_CHECK
|
||||
EXTRA_DIST = check_resources.sh
|
||||
|
||||
116
tests/simple-log.c
Normal file
116
tests/simple-log.c
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Red Hat, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Author: Angus Salkeld <asalkeld@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/>.
|
||||
*/
|
||||
#include "os_base.h"
|
||||
#include <signal.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <qb/qbdefs.h>
|
||||
#include <qb/qblog.h>
|
||||
|
||||
static void func_one(void) {
|
||||
qb_log(LOG_DEBUG, "hello");
|
||||
qb_log(LOG_CRIT, "hello");
|
||||
qb_log(LOG_ERR, "hello");
|
||||
qb_log(LOG_INFO, "hello");
|
||||
}
|
||||
|
||||
static void func_two(void) {
|
||||
qb_log(LOG_DEBUG, "arrrg!");
|
||||
qb_log(LOG_CRIT, "arrrg!");
|
||||
qb_log(LOG_ERR, "arrrg!");
|
||||
qb_log(LOG_INFO, "arrrg!");
|
||||
}
|
||||
|
||||
static void show_usage(const char *name)
|
||||
{
|
||||
printf("usage: \n");
|
||||
printf("%s <options>\n", name);
|
||||
printf("\n");
|
||||
printf(" options:\n");
|
||||
printf("\n");
|
||||
printf(" -v verbose\n");
|
||||
printf(" -h show this help text\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
#define MY_STDOUT_TAG 1
|
||||
#define MY_LOG_TAG 2
|
||||
|
||||
static void my_log_writer(struct qb_log_callsite *cs, const char *msg)
|
||||
{
|
||||
if (qb_bit_is_set(cs->tags, MY_STDOUT_TAG)) {
|
||||
fprintf(stdout, "[%s:%d] <%d> %s\n", cs->filename, cs->lineno, cs->priority, msg);
|
||||
}
|
||||
if (qb_bit_is_set(cs->tags, MY_LOG_TAG)) {
|
||||
syslog(cs->priority, "%s", msg);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t main(int32_t argc, char *argv[])
|
||||
{
|
||||
const char *options = "vh";
|
||||
int32_t opt;
|
||||
uint8_t priority = LOG_NOTICE;
|
||||
qb_log_filter_t* ls1;
|
||||
qb_log_filter_t* ls2;
|
||||
|
||||
while ((opt = getopt(argc, argv, options)) != -1) {
|
||||
switch (opt) {
|
||||
case 'v':
|
||||
priority++;
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
show_usage(argv[0]);
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
qb_log_handler_set(my_log_writer);
|
||||
|
||||
/* stdout logging */
|
||||
ls1 = qb_log_filter_create();
|
||||
qb_log_filter_priority_set(ls1, priority);
|
||||
qb_log_filter_file_add(ls1, __FILE__, 1, 33); // line 1 to 33
|
||||
qb_log_filter_file_add(ls1, __FILE__, 75, INT32_MAX); // line 75 to EOF
|
||||
qb_log_tag(ls1, QB_TRUE, MY_STDOUT_TAG);
|
||||
|
||||
/* syslog */
|
||||
ls2 = qb_log_filter_create();
|
||||
qb_log_filter_priority_set(ls2, LOG_WARNING);
|
||||
qb_log_tag(ls2, QB_TRUE, MY_LOG_TAG);
|
||||
|
||||
qb_log(LOG_DEBUG, "hello");
|
||||
qb_log(LOG_INFO, "hello");
|
||||
qb_log(LOG_NOTICE, "hello");
|
||||
func_one();
|
||||
func_two();
|
||||
qb_log_tag(ls2, QB_FALSE, MY_LOG_TAG);
|
||||
qb_log(LOG_WARNING, "no syslog");
|
||||
qb_log(LOG_ERR, "no syslog");
|
||||
|
||||
qb_log_filter_destroy(ls1);
|
||||
qb_log_filter_destroy(ls2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user