[Linux][C\C++] 一个简单的日志系统

minilogger介绍

minilogger日志模块是从rockchip rv1126 SDK中抽离的,可以直接移植到自己的项目中,
包含console串口输出和/var/log/syslog记录

源代码文件

backtrace.cpp、backtrace.h、log.cpp、log.h、main.cpp

backtrace.h

#ifndef  __MINILOG_BACKTRACE_H
#define __MINILOG_BACKTRACE_H
#ifdef __cplusplus
extern "C" {
#endif
void show_backtrace();
#ifdef __cplusplus
}
#endif

#endif /* __MINILOG_BACKTRACE_H */

backtrace.cpp

#include "backtrace.h"
#include "log.h"

#ifdef __cplusplus
#include <cxxabi,h>
#endif
#include <dlfcn.h>
#include <glib.h>
#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libgen.h>
#include <execinfo.h>

void show_backtrace(void) {
#define SIZE 100
	int nptrs;
	void *buffer[SIZE];
	char **strings;
	nptrs = backtrace(buffer, SIZE);
	strings = backtrace_symbols(buffer, nptrs);
	if (strings == NULL) {
		perror("backtrace_sysbols");
		exit(EXIT_FAILURE);
	}
	for (int j =0; j < nptrs; j++) {
		minilog_error("%s\n", strings[j]);
	}
	free(strings);
}

log.h

#ifndef  __MINILOG_LOG_H
#define __MINILOG_LOG_H
#ifdef __APPLE__
#define SECTION(X) section("__DATA,__" X)
#define SECTION_START(X) __asm("section$start$__DATA$__" X)
#define SECTION_END(X) __asm("section$end$__DATA$--" X)
#else
#define SECTION(X) section(X)
#define SECTION_START(X)
#define SECTION_END(X)
#endif

#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
struct minilog_debug_desc {
	const char *name;
	const char *file;
#define MINILOG_DEBUG_FLAG_DEFAULT (0)
#define MINILOG_DEBUG_FLAG_PRINT (1 << 0)
#define MINILOG_DEBUG_FLAG_ALIAS (1 << 1)
	unsigned int flags;
} __attribute__((aligned(8)));

int __minilog_log_init(const char *program, const char *debug, bool detach, bool backtrace, const char *program_name, const char *program_version);
void __minilog_log_cleanup(bool backtrace);
void __minilog_log_enable(staruct minilog_debug_desc *start, struct minilog_debug_desc *stop);

void minilog_info(const char *format, ...) __attribute__((format(print, 1, 2)));
void minilog_warn(const char *format, ...) __attribute__((format(print, 1, 2)));
void minilog_error(const char *format, ...) __attribute__((format(print, 1, 2)));
void minilog_debug(const char *format, ...) __attribute__((format(print, 1, 2)));

#define minilog_warn_once(fmt, ...) 							\
	do {														\
		static bool printed;									\
		if(!printed) {											\
			minilog_warn(fmt, __VA_ARGS__);						\
			printed = true;										\
		}														\
	} while (0)

#define MINILOG_DEBUG_DEFINE(name) 									\
	static struct minilog_debug_desc __debug_alias_##name 			\
		__attribute__((used, SECTION("__debug”), aligned(8))) = { 	\
			#name, __FILE__, MINILOG_DEBUG_FLAG_ALOAS};

#define DBG(fmt, ...)																\
	do {																			\
		static struct minilog_debug_desc __minilog_debug_desc						\
			__attribute__((used, SECTION("__debug"), aligned(8))) = {				\
				.file = __FILE__, 													\
				.flags = MINILOG_DEBUG_FLAG_DEFAULT, 								\
		}; 																			\
		if(__minilog_debug_desc.flags & MINILOG_DEBUG_FLAG_PRINT) 					\
			minilog_debug("%s:%s() " fmt, __FILE__, __FUNCTION__, __VA_ARGS__);	    \
	} while(0)
#ifdef __cplusplus
}
#endif

#endif /* __MINILOG_LOG_H */

log.cpp

#include "log.h"
#include "backtrace.h"

#include <dlfcn.h>
#include <glib.h>
#include <limits.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>

typedef void (*sighandler_t)(int);

static const char *program_exec;
static const char *program_path;

MINILOG_DEBUG_DEFINE(dummy)

void minilog_info(const char *format, ...) {
	va_list ap;
	va_start(ap, format);
	vsyslog(LOG_INFO, format, ap);
	va_end(ap);
}
void minilog_warn(const char *format, ...) {
	va_list ap;
	va_start(ap, format);
	vsyslog(LOG_WARNING, format, ap);
	va_end(ap);
}
void minilog_error(const char *format, ...) {
	va_list ap;
	va_start(ap, format);
	vsyslog(LOG_ERR, format, ap);
	va_end(ap);
}
void minilog_debug(const char *format, ...) {
	va_list ap;
	va_start(ap, format);
	vsyslog(LOG_DEBUG, format, ap);
	va_end(ap);
}

static void signal_handler(int signo) {
	minilog_error("Aborting (signal %d) [%s]", signo, program_exec);
	show_backtrace();
	exit(EXIT_FAILURE);
}

static void signal_setup(signaler_t handler) {
	struct sigaction sa;
	sigset_t mask;
	
	sigemptyset(&mask);
	sa.sa_handler = handler;
	sa.sa_mask = mask;
	sa.sa_flags = 0;
	sigaction(SIGBUS, &sa, NULL);
	sigaction(SIGILL, &sa, NULL);
	sigaction(SIGFPE, &sa, NULL);
	sigaction(SIGSEGV, &sa, NULL);
	sigaction(SIGABRT, &sa, NULL);
	sigaction(SIGPIPE, &sa, NULL);
}

#if !__APPLE__
extern struct minilog_debug_desc __start___debug[];
extern struct minilog_debug_desc __stop___debug[];
#endif

static char **enabled = NULL;

static bool is_enabled(struct minilog_debug_desc *desc) {
	int i;
	if(!enabled)
		return false;
	for(i = 0; enable[i]; i++) {
		if(desc->name && g_pattern_match_simple(enabled[i], desc->name))
			return true;
		if(desc->file && g_pattern_match_simple(enabled[i], desc->file))
			return true;
	}
	return false;
}

void __minilog_log_enable(struct minilog_debug_desc *start, struct minilog_debug_desc *stop) {
	struct minilog_debug_desc *desc;
	const char *name = NULL, *file = NULL;
	if(!start || !stop)
		return;
	for(desc = start; desc < stop; desc++) {
		if (desc->flags & MINILOG_DEBUG_FLAG_ALIAS) {
			file = desc->file;
			name = desc->name;
			continue;
		}
		if (file || name) {
			if(strcmp(desc->file, file) == 0) {
				if (!desc->name)
					desc->name = name;
			} else
				file = NULL;
		}
		if (is_enabled(desc))
			desc->flags |= MINILOG_DEBUG_FLAG_PRINT;
 	}
}

int __minilog_log_init(const char *program, const char *debug, bool detach, bool backtrace, const char *program_name, const char *program_version) {
	static char path[PATH_MAX];
	int option = LOG_NDELAY | LOG_PID;
	program_exec = program;
	program_path = getcmd(path, sizeof(path));

	if(debug)
		enabled = g_strsplit_set(debug, ":, ", 0);
#if !__APPLE__
	__minilog_log_enable(__start___debug, __stop___debug);
#endif

	if(!detach)
		option |= LOG_PERROR;
	
	if(backtrace)
		signal_setup(signal_handler);

#if !__APPLE__
	openlog(basename(program), option, LOG_DAEMON);
#else
	openlog(g_path_get_basename(program), option, LOG_DAEMON);
#endif
	syslog(LOG_INFO, "%s version %s", program_name, program_version);
	return 0;
}

void __minilog_log_cleanup(bool backtrace) {
	syslog(LOG_INFO, "Exit");

	closelog();
	if(backtrace) {
		signal_setup(SIG_DFL);
	}
	g_strfreev(enabled);
}

main.cpp

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>

#include "backtrace.h"
#include "log.h"

void foo2(void) {
	minilog_info("11111111111111111111");
}

void foo1(void) {
	foo2();
}
int main(int argc, char **argv) {
	__minilog_log_init(argv[0], NULL,false, true, "trace_cpp", "1.1");
	foo1();
	return 0;
}

编译方式:

gcc main.cpp log.cpp backtrace.cpp -lglib-2.0 -I/usr/include/glib-2.0/
./a.out 
串口log

syslog
tail /var/log/syslog
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值