一、跨平台编译
1)编译准备
(1)expat编译
- linux编译
传送门 - win编译
1)下载
https://libexpat.github.io/
https://github.com/libexpat/libexpat/releases
2)将下载的源码文件“libexpat-R_2_4_4.zip”解压之后,
由于源码文件里已经提供了CMakeLists.txt,所有直接使用cmake加载脚本构建生成VS工程文件。
3)方法2:使用大家常用的cmake的命令行操作,如下:
## 1、打开源代码文件夹
cd C:\Users\tomcat\Desktop\libexpat-R_2_4_4\expat
## 2、新建编译输出文件夹
mkdir build
## 3、进入编译输出文件夹
cd build
## 4、生成.sln工程文件
cmake ..
## 5、编译代码
cmake --build .
4)编译完毕之后,生成的dll和lib文件如下:
2)原生linux编译、安装
-
下载位置
http://log4c.sourceforge.net/ -
编译安装指令
$ gzip -dc log4c-1.2.4.tar.gz | tar tvf -
$ cd log4c-1.2.4/
$ ./configure --enable-static --prefix=/home/ww/ww/gitlabproject/opcodetester/third/log4c-install/ CC="gcc -m32"
$ make
$ make install
3)cmake跨平台编译
- 第三方库expat的相关编译好的文件放进来,如下:
- 编写测试案例
编写一个简单的测试文件“ConsoleApplication1.cpp”,放在log4c文件夹里的examples子文件夹里。
- ConsoleApplication1.cpp:
#include <iostream>
#include "log4c.h"
#ifdef _DEBUG
#pragma comment(lib, "..\\lib\\Win32\\Debug\\log4cd.lib")
#else
#pragma comment(lib, "..\\lib\\Win32\\Release\\log4c.lib")
#endif
int main()
{
std::cout << "Hello World!\n";
log4c_init();
log4c_category_t* mylog = log4c_category_get("framework");
log4c_category_log(mylog, LOG4C_PRIORITY_DEBUG, "Hello World!");
log4c_category_t* mycat = NULL;
mycat = log4c_category_get("six13log.log.app.application2");
log4c_category_log(mycat, LOG4C_PRIORITY_DEBUG, "Debugging app 2");
log4c_category_log(mycat, LOG4C_PRIORITY_ERROR,
"some error from app2 at line %d in file %s",
__LINE__, __FILE__);
log4c_fini();
}
- 新建文件config.h
将log4c子文件夹src里面的“config.h.in”文件,复制出一份,改名为config.h。
通过将config.h内容修改如下:
/* src/config.h.in. Generated from configure.in by autoheader. */
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
systems. This function is required for `alloca.c' support on those systems.
*/
#undef CRAY_STACKSEG_END
/* Define to 1 if using `alloca.c'. */
#undef C_ALLOCA
/* Define to 1 if you have `alloca', as a function or macro. */
#undef HAVE_ALLOCA
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
*/
#undef HAVE_ALLOCA_H
/* Define to 1 if you have the <alloc.h> header file. */
#undef HAVE_ALLOC_H
/* Define to 1 if you have the declaration of `gmtime_r', and to 0 if you
don't. */
#undef HAVE_DECL_GMTIME_R
/* Define to 1 if you have the declaration of `localtime_r', and to 0 if you
don't. */
#undef HAVE_DECL_LOCALTIME_R
/* Define to 1 if you have the declaration of `sleep', and to 0 if you don't.
*/
#undef HAVE_DECL_SLEEP
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
#undef HAVE_DOPRNT
/* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define to 1 if you have the `gethostname' function. */
#undef HAVE_GETHOSTNAME
/* Define to 1 if you have the <getopt.h> header file. */
#undef HAVE_GETOPT_H
/* Define to 1 if you have the `getpagesize' function. */
#undef HAVE_GETPAGESIZE
/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
/* Define to 1 if you have the `gmtime_r' function. */
#undef HAVE_GMTIME_R
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the <langinfo.h> header file. */
#undef HAVE_LANGINFO_H
/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
/* Define to 1 if you have the `localtime_r' function. */
#undef HAVE_LOCALTIME_R
/* Define to 1 if you have the <malloc.h> header file. */
//#undef HAVE_MALLOC_H
#define HAVE_MALLOC_H
/* Define to 1 if you have the <memory.h> header file. */
//#undef HAVE_MEMORY_H
/* Define to 1 if you have the `memset' function. */
//#undef HAVE_MEMSET
/* Define to 1 if you have a working `mmap' system call. */
#undef HAVE_MMAP
/* Define to 1 if you have the `munmap' function. */
#undef HAVE_MUNMAP
/* Define to 1 if you have the `nl_langinfo' function. */
#undef HAVE_NL_LANGINFO
/* Define to 1 if you have the <pthread.h> header file. */
#undef HAVE_PTHREAD_H
/* Define to 1 if you have the `sbrk' function. */
#undef HAVE_SBRK
/* Define to 1 if you have the `sleep' function. */
#undef HAVE_SLEEP
/* Define to 1 if you have the <stdarg.h> header file. */
//#undef HAVE_STDARG_H
#define HAVE_STDARG_H
/* Define to 1 if you have the <stddef.h> header file. */
//#undef HAVE_STDDEF_H
#define HAVE_STDDEF_H
/* Define to 1 if you have the <stdint.h> header file. */
//#undef HAVE_STDINT_H
#define HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
//#undef HAVE_STDLIB_H
#define HAVE_STDLIB_H
/* Define to 1 if you have the `strdup' function. */
#undef HAVE_STRDUP
/* Define to 1 if you have the `strerror' function. */
#undef HAVE_STRERROR
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the `strncasecmp' function. */
#undef HAVE_STRNCASECMP
/* Define to 1 if you have the `strrchr' function. */
#undef HAVE_STRRCHR
/* Define to 1 if you have the `strstr' function. */
#undef HAVE_STRSTR
/* Define to 1 if you have the <syslog.h> header file. */
#undef HAVE_SYSLOG_H
/* Define to 1 if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the `utime' function. */
#undef HAVE_UTIME
/* Define to 1 if you have the <utime.h> header file. */
#undef HAVE_UTIME_H
/* Define to 1 if `utime(file, NULL)' sets file's timestamp to the present. */
#undef HAVE_UTIME_NULL
/* Define to 1 if you have the <varargs.h> header file. */
#undef HAVE_VARARGS_H
/* Define to 1 if you have the `vprintf' function. */
#undef HAVE_VPRINTF
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#undef LT_OBJDIR
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at runtime.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
#undef STACK_DIRECTION
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME
/* Define to 1 if your <sys/time.h> declares `struct tm'. */
#undef TM_IN_SYS_TIME
/* Version number of package */
//#undef VERSION
#define VERSION "1.2.4"
#define LOG4C_RCPATH "d:"
/* build log4c with initialization constructors */
#undef WITH_CONSTRUCTORS
/* Define if we found pthread.h libpthread */
#undef WITH_ROLLINGFILE
/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
`char[]'. */
#undef YYTEXT_POINTER
/* "POSIXandGNU extensions" */
#undef _GNU_SOURCE
/* Enable automatic reread of log4crc file */
#undef __ENABLE_REREAD__
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
#undef inline
#endif
/* Define to `unsigned int' if <sys/types.h> does not define. */
//#undef size_t
/* Trying to use __va_copy on non-C89 systems */
//#undef va_copy
- 编写cmake
在log4c-1.2.4里面创建CMakeLists.txt
cmake_minimum_required (VERSION 2.8.12) //可以写高点版本
project (log4c) //定义项目名字
# add flag
add_definitions(-DHAVE_CONFIG_H) //-D定义宏HAVE_CONFIG_H
add_definitions(-D_CRT_SECURE_NO_WARNINGS) //去除warning警告
# add var
set(CMAKE_DEBUG_POSTFIX d)
if(CMAKE_SIZEOF_VOID_P EQUAL 4)
set(ARCH_POSTFIX "Win32")
else()
set(ARCH_POSTFIX x64)
endif()
IF (CMAKE_BUILD_TYPE MATCHES "Release")
SET(CMAKE_BUILD_POSTFIX "${CMAKE_RELEASE_POSTFIX}")
ELSEIF (CMAKE_BUILD_TYPE MATCHES "MinSizeRel")
SET(CMAKE_BUILD_POSTFIX "${CMAKE_MINSIZEREL_POSTFIX}")
ELSEIF(CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo")
SET(CMAKE_BUILD_POSTFIX "${CMAKE_RELWITHDEBINFO_POSTFIX}")
ELSEIF(CMAKE_BUILD_TYPE MATCHES "Debug")
SET(CMAKE_BUILD_POSTFIX "${CMAKE_DEBUG_POSTFIX}")
ELSE()
SET(CMAKE_BUILD_POSTFIX "")
ENDIF()
# add .c and .cpp
include_directories (./src ./src/log4c ./src/sd )
aux_source_directory (./src/log4c DIR_SRCS1)
aux_source_directory (./src/sd DIR_SRCS2)
list(REMOVE_ITEM DIR_SRCS1 "./src/log4c/appender_type_mmap.c")
list(REMOVE_ITEM DIR_SRCS1 "./src/log4c/appender_type_mmap.h")
list(REMOVE_ITEM DIR_SRCS1 "./src/log4c/appender_type_mmap.h")
list(REMOVE_ITEM DIR_SRCS2 "./src/sd/sprintf.osf.c")
list(REMOVE_ITEM DIR_SRCS2 "./src/sd/domnode.c")
# add link dir
link_directories("./libexpat-R_2_4_4/lib/${ARCH_POSTFIX}")
# create dll(project1) or lib(project2)
add_library (log4c_shared SHARED ${DIR_SRCS1} ${DIR_SRCS2})
add_library (log4c_static STATIC ${DIR_SRCS1} ${DIR_SRCS2})
set_target_properties (log4c_shared PROPERTIES OUTPUT_NAME "log4c")
set_target_properties (log4c_static PROPERTIES OUTPUT_NAME "log4c_static")
set (LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib/${ARCH_POSTFIX})
set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin/${ARCH_POSTFIX})
target_compile_definitions( log4c_shared PRIVATE LOG4C_EXPORTS )
target_compile_definitions( log4c_static PRIVATE LOG4C_EXPORTS )
# add libexpat library
list(APPEND EXTRA_LIBS libexpat)
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/libexpat-R_2_4_4/include")
target_link_libraries(log4c_shared PUBLIC ${EXTRA_LIBS})
target_include_directories(log4c_shared PUBLIC "${PROJECT_BINARY_DIR}" ${EXTRA_INCLUDES})
target_link_libraries(log4c_static PUBLIC ${EXTRA_LIBS})
target_include_directories(log4c_static PUBLIC "${PROJECT_BINARY_DIR}" ${EXTRA_INCLUDES})
# create project3
add_executable(test ./examples/ConsoleApplication1.cpp)
- 这里用到的配置文件
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE log4c SYSTEM "">
<log4c version="1.2.4">
<config>
<bufsize>0</bufsize>
<debug level="2"/>
<nocleanup>0</nocleanup>
<reread>1</reread>
</config>
<category name="root" priority="notice"/>
<category name="six13log.log" priority="error" appender="stdout" />
<rollingpolicy name="myrollingpolicy" type="sizewin" maxsize="1024" maxnum="10" />
<appender name="myrollingfileappender" type="rollingfile" logdir="." prefix="myprefix" layout="dated" rollingpolicy="myrollingpolicy" />
<appender name="stdout" type="stream" layout="basic"/>
<appender name="stderr" type="stream" layout="dated"/>
<appender name="syslog" type="syslog" layout="basic"/>
<appender name="s13file" type="s13_file" layout="basic"/>
<appender name="plain_stderr" type="s13_stderr" layout="none"/>
<appender name="cat_stderr" type="s13_stderr" layout="catlayout"/>
<appender name="xml_stderr" type="s13_stderr" layout="xmllayout"/>
<appender name="user_stderr" type="s13_stderr" layout="userlayout"/>
<layout name="basic" type="basic"/>
<layout name="dated" type="dated"/>
<layout name="catlayout" type="s13_cat"/>
<layout name="xmllayout" type="s13_xml"/>
<layout name="none" type="s13_none"/>
<layout name="userlayout" type="s13_userloc"/>
<category name="six13log.log.app.application2" priority="debug" appender="cat_stderr" />
<category name="six13log.log.app.application3" priority="debug" appender="user_stderr" />
<category name="six13log.log.app" priority="debug" appender="myrollingfileappender" />
</log4c>
- cmake生成VS工程(这里方便没放build,一般都是创建build目录放里面)
二、log4c配置笔记
1)与log4cpp\log4cxx的比较
①Log4cpp & Log4CPlus:C++的日志库,可移植移性相对差些;Log4cxx需要依赖于APR
②Log4c:C的日志库,基本上都是一些纯c的东西,移植性较好
2)log4c的三个基本概念简单介绍(Category, Appender, Layout)
- 概念说明
①Category:用于区分不同的日志,在一个程序中我们可以通过Category来指定很多的日志。
②Appdender:用于描述输出流,通过为Category来指定一个Appdender,可以决定将log信息来输出到什么地方去,比如stdout, stderr, rollingfile等等。(rollingpolicy用于描述文件输出的配置策略。)
③Layout:用于指定日志信息的格式,通过为Appender来指定一个Layout,可以决定log信息以何种格式来输出,比如是否有带有时间戳, 是否包含文件位置信息等,以及他们在一条log信息中的输出格式的等。 - 组合关系
Category, Appender, Layout三者之间的关系,一个Category需要为其指定一个appender, 一个appender亦要为其指定一个layout。
3)配置文件示例
<!DOCTYPE log4c SYSTEM "">
<log4c version="1.2.0">
<config>
<bufsize>0</bufsize>
<debug level="0"/>
<nocleanup>0</nocleanup>
</config>
<layout name="dated" type="dated_l"/>
<!-- appenders ===================================== -->
<appender name="LoadBusinessLog" type="rollingfile" logdir="../etc/log"
prefix="LoadBusiness-" layout="dated_l" rollingpolicy="Policy1" />
<appender name="CataRollingFileAppender" type="rollingfile" logdir="../etc/log/"
prefix="testLog" layout="dated" rollingpolicy="RollingPolicy" />
//输出流名字CataRollingFileAppender,输出流类型rollingfile,输出日志地址../etc/log
//输出日志格式名字是dated,输出日志文件配置策略名称RollingPolicy
<!-- category ========================================= -->
<category name="root" priority="notice"/>
// 日志名字叫root,优先级是notice
<category name="framework" priority="info" appender="FrameLog" />
// 日志名字叫framework,优先级是info,appender输出流类型名称选择FrameLog
<category name="test.log" priority="trace" appender="CataRollingFileAppender" />
//日志名字叫test.log,优先级是trace,appender输出流类型名称选择CataRollingFileAppender
<!-- rollingpolicy ======================================= -->
<rollingpolicy name="Policy1" type="timewin" timetype="1" maxnum="10" />
//日志文件输出的配置策略名称为Policy1,日志文件输出的配置策略的类型为timewin
//maxsize:输出日志文件的最大值。默认值为20KB;
//maxnum:保存的历史日志文件总数。默认值为5
<rollingpolicy name="RollingPolicy" type="sizewin" maxsize="102400" maxnum="10" />
</log4c>
三、log4c概念详细介绍
1)category
①name:日志的名称
②priority:日志的优先级,共有fatal、alert、crit、error、warn、notice、info、debug、trace、notset和unknown11个级别,其级别逐步递增,记录在日志中的数据为小于等于指定级别的数据。
③appender:输出流类型名称,为appender节点的name属性的值。
2)appender
①name:输出流名称
②type:输出流类型,共有stream、syslog、rollingfile三大类
③layout:输出日志的格式的名称,为layout节点的name属性的值。
④rollingpolicy:输出日志文件配置策略名称,为rollingpolicy节点的name属性的值。
⑤rollingpolicy的timewin类型的日志输出为自定义类型
3)layout
①name:输出日志的格式名称
②type:输出日志格式的类型,共有base 、dated、dated_l等格式类型,对于自定义类型也有配置在这里,否则不能够加载。
③base:%P %c - %m/n
“%P” 日志信息的优先级
“%c” 日志的名称
“%m” 日志信息内容
④dated:%d %P %c - %m/n --包含时间
“%d” 日志信息产生的时间,UTC格式yyyymmdd hh:mm:ss.mis
“%P” 日志信息的优先级
“%c” 日志的名称
“%m” 日志信息内容
⑤dated_l:%d %P %c - %m/n (源代码里面没有,自己增加的)
“%d” 日志信息产生的时间,本地时间格式yyyymmdd hh:mm:ss
“%P” 日志信息的优先级
“%c” 日志的名称
"%m"日志信息内容
4)rollingpolicy
①name:日志文件输出的配置策略名称。
②type:日志文件输出的配置策略的类型,有sizewin一种类型。
③maxsize:输出日志文件的最大值。默认值为20KB
④maxnum:保存的历史日志文件总数。默认值为5
5)配置文件的路径 :
①${ LOG4C_RCPATH }/log4crc //环境变量中设置的配置文件夹下log4crc
②${HOME}/.log4crc //HOME文件夹下log4crc
③/log4crc //当前可执行文件夹下log4crc
6)环境变量
1)LOG4C_RCPATH:
holds the path to the main log4crc configuration file
#环境变量若未设置,则在工作目录(一般为运行目录)搜索log4crc配置文件. 如果设置了此变量,则所以用log4c库的程序都会使用此路径下的log4c配置文件(可根据category区分).
2)LOG4C_PRIORITY
holds the "root" category priority
#改变root的priority,,
3)LOG4C_APPENDER
holds the "root" category appender
#改变root的appender,,因为root默认没设置appender.
四、log4c代码使用案例及简答封装实例
1)引用头文件注意点
- 直接引用log4c.h程序编译出错,因此只引用需要的头文件
extern "C" {
#include <log4c/init.h>
#include <log4c/category.h>
}
2)原生实例代码
//.cpp文件
//初始化
int main()
{
log4c_init();
//获取一个已有的category
log4c_category_t* mycat = log4c_category_get("cata.log ");
//用该category进行日志输出,优先级为DEBUG,输出信息为 "Hello World!"
log4c_category_log(mycat, LOG4C_PRIORITY_DEBUG, "Hello World!");
//析构
log4c_fini();
}
//////备注//////
//在日志输出过程中可以进行格式化输出:
log4c_category_log(mycat, LOG4C_PRIORITY_ERROR, "Error code = %d", 12345);
//对于格式化输出也可以有如下写法:
void CLog::Trace(const char * format, ... )
{
if (log4c_category_is_priority_enabled(mycat, LOG4C_PRIORITY_TRACE))
{
a_list argptr;
va_start(argptr, format);
log4c_category_vlog(mycat, LOG4C_PRIORITY_TRACE, format, argptr);
va_end(argptr);
}
}
3)类C简单封装
(1)log.h
#ifndef _LOG_H_
#define _LOG_H_
#include <string.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C"
{
#endif
#include "log4c.h"
#ifdef __cplusplus
}
#endif
#define LOG_PRI_ERROR LOG4C_PRIORITY_ERROR
#define LOG_PRI_WARN LOG4C_PRIORITY_WARN
#define LOG_PRI_NOTICE LOG4C_PRIORITY_NOTICE
#define LOG_PRI_DEBUG LOG4C_PRIORITY_DEBUG
#define LOG_PRI_TRACE LOG4C_PRIORITY_TRACE
//log_open("category_name"); //category_name一定得是log4crc里面已经定义的category.
extern int log_open(const char *category);
extern void log_message(int priority ,const char* fmt, ...);
extern void log_trace(const char *file , int line , const char *func, const char *fmt ,...);
extern int log_close();
#define LOG_ERROR(fmt , args...) \
log_message(LOG_PRI_ERROR, fmt, ##args)
#define LOG_WARN(fmt, args...) \
log_message(LOG_PRI_WARN, fmt , ##args)
#define LOG_NOTICE(fmt , args...) \
log_message(LOG_PRI_NOTICE, fmt , ##args)
#define LOG_DEBUG(fmt , args...) \
log_message(LOG_PRI_DEBUG, fmt , ##args)
#define LOG_TRACE(fmt,args...) \
log_trace(__FILE__ , __LINE__ , __FUNCTION__ , fmt ,## args)
#endif
(2)log.c
#include <log4c.h>
#include <assert.h>
#include "log.h"
static log4c_category_t *log_category = NULL;
//log_open("category_name"); //category_name一定得是log4crc里面已经定义的category.
int log_open(const char *category)
{
if (log4c_init() == 1)
{
return -1;
}
log_category = log4c_category_get(category);
return 0 ;
}
void log_message(int priority , const char *fmt , ...)
{
va_list ap;
assert(log_category != NULL);
va_start(ap, fmt);
log4c_category_vlog(log_category , priority , fmt , ap);
va_end(ap);
}
void log_trace(const char *file, int line, const char *fun,
const char *fmt , ...)
{
char new_fmt[2048];
const char *head_fmt = "[file:%s, line:%d, function:%s]";
va_list ap;
int n;
assert(log_category != NULL);
n = sprintf(new_fmt, head_fmt , file , line , fun);
strcat(new_fmt + n , fmt);
va_start(ap , fmt);
log4c_category_vlog(log_category , LOG4C_PRIORITY_TRACE, new_fmt , ap);
va_end(ap);
}
int log_close()
{
return (log4c_fini());
}
(3)测试代码test-log.c
#include <stdio.h>
#include "log.h"
int main(void)
{
log_open("<span style="color: rgb(51, 51, 51); line-height: 20px;">mycat</span>");
LOG_TRACE("trace");
LOG_ERROR("error");
LOG_WARN("warn");
LOG_NOTICE("notice");
LOG_DEBUG("hello log4c!");
log_close();
return 0;
}
(4)配置文件(默认名为log4crc.xml)
- 备注
配置文件的搜索是由LOG4C_RCPATH环境变量决定。搜索的配置文件名为log4crc
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE log4c SYSTEM "">
<log4c version="1.2.1">
<config>
<bufsize>0</bufsize>
<debug level="2"/>
<nocleanup>0</nocleanup>
<reread>1</reread>
</config>
<!-- root category ========================================= -->
<category name="root" priority="notice"/>
<category name="mycat" priority="debug" appender="stdout"/>
<!-- default appenders ===================================== -->
<appender name="stdout" type="stream" layout="basic"/>
<appender name="stderr" type="stream" layout="dated"/>
<appender name="syslog" type="syslog" layout="basic"/>
<!-- default layouts ======================================= -->
<layout name="basic" type="basic"/>
<layout name="dated" type="dated"/>
</log4c>
(5)运行效果
./test-log
[stdout] TRACE mycat - [file:test-log.c, line:7, function:main]trace
[stdout] ERROR mycat - error
[stdout] WARN mycat - warn
[stdout] NOTICE mycat - notice
[stdout] DEBUG mycat - hello log4c!
4)类C++单例封装
(1)log.h
#ifndef LOG_H
#define LOG_H
#include <log4c/init.h>
#include <log4c/category.h>
class MyLog
{
public:
void init(const char * str);
static MyLog * get_instance();
log4c_category_t * mycat;
private:
MyLog();
~MyLog();
private:
static MyLog * _instance;
};
#define LOG_DEBUG(msg, args...) \
{ \
const log4c_location_info_t locinfo = LOG4C_LOCATION_INFO_INITIALIZER(NULL); \
log4c_category_log_locinfo(MyLog::get_instance()->mycat, &locinfo, LOG4C_PRIORITY_DEBUG, msg, ##args); \
}
#define LOG_ERROR(msg, args...) \
{ \
const log4c_location_info_t locinfo = LOG4C_LOCATION_INFO_INITIALIZER(NULL); \
log4c_category_log_locinfo(MyLog::get_instance()->mycat, &locinfo, LOG4C_PRIORITY_ERROR, msg, ##args); \
}
#define LOG_TRACE(msg, args...) \
{ \
const log4c_location_info_t locinfo = LOG4C_LOCATION_INFO_INITIALIZER(NULL); \
log4c_category_log_locinfo(MyLog::get_instance()->mycat, &locinfo, LOG4C_PRIORITY_TRACE, msg, ##args); \
}
#endif
(2)log.cpp
#include <stdio.h>
#include "log.h"
MyLog * MyLog::_instance = NULL;
MyLog::MyLog()
{
}
MyLog::~MyLog()
{
if (log4c_fini() != 0)
printf("log4c fini error!\n");
}
void MyLog::init(const char * str)
{
if (log4c_init() != 0) {
printf("log4c init error!\n");
return;
}
mycat = log4c_category_get(str);
}
MyLog * MyLog::get_instance()
{
if (_instance == NULL) {
_instance = new MyLog;
} else {
}
return _instance;
}
(3)main.cpp
#include "classA.h"
#include "classB.h"
//#include <log4c/init.h>
//#include <log4c/category.h>
#include "log.h"
int main(int argc,char** argv)
{
MyLog::get_instance()->init("zhenglq");
ClassA ca;
ClassB cb;
ca.printStr();
cb.printStr();
/* log4c init */
// log4c_init();
/* get category */
// log4c_category_t* mycat = log4c_category_get("aiwujie");
/* out log */
// log4c_category_log(mycat, LOG4C_PRIORITY_DEBUG,"Hello World!");
// log4c_fini();
LOG_DEBUG("hello log4c!");
return 0;
}
(4)配置文件log4crc
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE log4c SYSTEM "">
<log4c>
<config>
<bufsize>0</bufsize>
<debug level="0"/>
<nocleanup>0</nocleanup>
</config>
<category name="root" priority="notice"/>
<appender name="log4.log" type="stream" layout="dated" logdir="." prefix="testLog"/>
<layout name="dated" type="dated"/>
<category name="aiwujie" priority="debug" appender="log4.log"/>
</log4c>