開源純C日誌函數庫iLOG3快速入門(1、基本使用速覽)

關鍵軟件都要有日誌,有的用本身寫的簡單寫日誌函數,但缺少一些必要的功能如日誌等級、日誌分類和轉檔,有的用諸如log4c這樣的巨無霸,功能很豐富,但太臃腫了,執行效率也大打折扣。今天我向你們推薦一款輕巧易用的日誌函數庫iLOG3,但願你們能喜歡 ^_^

iLOG3是一個輕便易用、概念簡單,高性能、多層接口、原生跨平臺、(規範使用時)線程安全的遵循LGPL開源協議的標準c日誌函數庫。

基本特性以下:
·原生跨平臺,這意味着你的軟件在日誌層面上是可輕鬆移植的,目前支持WINDOWS & UNIX & Linux ,iLOG3會在不一樣的操做系統上作相應的實現和優化
·五類日誌等級
·變參的日誌函數和日誌宏
·行日誌風格方案選配
·輸出介質有文件、標準輸出、標準錯誤輸出、syslogd或WINDOWS EVENT、自定義介質

高級特性以下:
·支持日誌選項組合
·支持按日誌文件大小、天天、每小時轉檔
·支持行日誌風格自定義回調函數,很容易定製本身的行日誌格式
·支持日誌文件的打開、輸出、關閉自定義回調函數,很容易擴展成日誌輸出到遠程日誌服務器落地
·線程安全、簡易MDC、基於線程本地存儲的缺省全局日誌句柄

分層實施「日誌句柄層(LOG)->日誌句柄集合層(LOGS)->配置文件接口層(LOGCONF、LOGSCONF)」。其實大部分用戶的日誌需求很簡單,一個進程寫一個日誌文件(使用日誌句柄層函數便可),但也考慮到另一些用戶有多個輸出對象需求(使用日誌句柄集合層函數便可),還有用戶喜歡用外部配置文件來配置日誌(使用配置文件接口層函數便可),不一樣用戶在不一樣項目場景中使用iLOG3的不一樣層接口,不至於殺雞用牛刀、小刀砍大樹。

此外,源代碼結構也比較簡單,只有三對源文件,便於搬運、嵌入和修改。

不說廢話,直接上使用代碼

#include <stdio.h>

#include "LOG.h"

#define LOG_STYLES_HELLO        ( LOG_STYLE_DATETIMEMS | LOG_STYLE_LOGLEVEL | LOG_STYLE_PID | LOG_STYLE_TID | LOG_STYLE_SOURCE | LOG_STYLE_FORMAT | LOG_STYLE_NEWLINE )

int test_LOG()
{
        char                buffer[ 64 + 1 ] = "" ;
        long                buflen = sizeof(buffer)-1 ;
        
        /* 建立日誌句柄 */
        if(CreateLogHandleG() == NULL )
        {
                printf( "建立日誌句柄失敗errno[%d]\n" , errno );
                return -1;
        }
        else
        {
                printf( "建立日誌句柄成功\n" );
        }
        
        /* 設置日誌輸出文件名 */
        SetLogOutputG( LOG_OUTPUT_FILE , "test_LOG.log" , LOG_NO_OUTPUTFUNC );
        /* 設置當前日誌過濾等級 */
        SetLogLevelG( LOG_LEVEL_INFO );
        /* 設置當前行日誌風格方案 */
        SetLogStylesG( LOG_STYLES_HELLO , LOG_NO_STYLEFUNC);
        
        /* 以不一樣日誌等級寫行日誌 */
        DEBUGLOGG( "hello DEBUG" ); /* 這行日誌因等級不夠,被華麗的過濾了 */
        INFOLOGG( "hello INFO" );
        WARNLOGG( "hello WARN" );
        ERRORLOGG( "hello ERROR" );
        FATALLOGG( "hello FATAL" );
        
        /* 以不一樣日誌等級寫十六進制塊日誌 */
        DEBUGHEXLOGG( buffer , buflen , "hello DEBUG buffer[%ld]" , buflen ); /* 又一個被華麗的過濾 */
        INFOHEXLOGG( buffer , buflen , "hello INFO buffer[%ld]" , buflen );
        WARNHEXLOGG( buffer , buflen , "hello WARN buffer[%ld]" , buflen );
        ERRORHEXLOGG( buffer , buflen , "hello ERROR buffer[%ld]" , buflen );
        FATALHEXLOGG( buffer , buflen , "hello FATAL buffer[%ld]" , buflen );
        
        /* 銷燬日誌句柄 */
        DestroyLogHandleG();
        printf( "釋放日誌句柄\n" );
        
        return 0;
}

int main()
{
        return -test_LOG();
}

說明一下,代碼先建立了一個日誌句柄,設置一些屬性,而後刷刷刷的寫日誌,最後銷燬日誌句柄。
編譯、連接、執行 html

$ gcc -g -fPIC -Wall -Werror -O2 -I. -std=c99 -I/home/calvin/exinc/iLOG3  -c test_LOG.c
$ gcc -g -fPIC -Wall -Werror -O2 -o test_LOG test_LOG.o -L. -std=c99 -L/home/calvin/exlib -liLOG3
$ ./test_LOG
建立日誌句柄成功
釋放日誌句柄
$ cat test_LOG.log
2014-02-10 00:26:07.418678 | INFO  | 2045:3086292688:test_LOG.c:32 | hello INFO
2014-02-10 00:26:07.419236 | WARN  | 2045:3086292688:test_LOG.c:33 | hello WARN
2014-02-10 00:26:07.419506 | ERROR | 2045:3086292688:test_LOG.c:34 | hello ERROR
2014-02-10 00:26:07.419518 | FATAL | 2045:3086292688:test_LOG.c:35 | hello FATAL
2014-02-10 00:26:07.419529 | INFO  | 2045:3086292688:test_LOG.c:39 | hello INFO buffer[64]
            0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F    0123456789ABCDEF
0x00000000   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000010   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000020   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000030   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
2014-02-10 00:26:07.419586 | WARN  | 2045:3086292688:test_LOG.c:40 | hello WARN buffer[64]
            0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F    0123456789ABCDEF
0x00000000   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000010   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000020   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000030   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
2014-02-10 00:26:07.419627 | ERROR | 2045:3086292688:test_LOG.c:41 | hello ERROR buffer[64]
            0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F    0123456789ABCDEF
0x00000000   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000010   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000020   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000030   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
2014-02-10 00:26:07.419686 | FATAL | 2045:3086292688:test_LOG.c:42 | hello FATAL buffer[64]
            0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F    0123456789ABCDEF
0x00000000   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000010   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000020   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000030   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
你想一第二天志輸出到多個對象(文件、標準輸出、標準錯誤輸出、syslogd或WINDOWS EVENT、遠程日誌服務器等),沒問題,咱們用一個LOGS包兩個LOG就能夠了,看代碼

#include <stdio.h>

#include "LOGS.h"

#define LOG_STYLES_DOG        ( LOG_STYLE_DATETIMEMS | LOG_STYLE_LOGLEVEL | LOG_STYLE_PID | LOG_STYLE_TID | LOG_STYLE_SOURCE | LOG_STYLE_FORMAT | LOG_STYLE_NEWLINE )
#define LOG_STYLES_EVENT      ( LOG_STYLE_DATETIMEMS | LOG_STYLE_CUSTLABEL1 | LOG_STYLE_FORMAT | LOG_STYLE_NEWLINE )

int test_LOGS()
{
	LOGS		*gs = NULL ;
	LOG		*g = NULL ;
        char		buffer[ 64 + 1 ] = "" ;
        long		buflen = sizeof(buffer)-1 ;
        
        /* 建立日誌句柄集合 */
        gs = CreateLogsHandleG() ; /* 帶後綴G的函數建立的日誌句柄集合自動設置成線程安全的全局缺省日誌句柄集合 */
        if( gs == NULL )
        {
                printf( "建立日誌句柄集合失敗errno[%d]\n" , errno );
                return -1;
        }
        else
        {
                printf( "建立日誌句柄集合成功\n" );
        }
        
        /* 建立日誌句柄 */
        g = CreateLogHandle() ;
        if( g == NULL )
        {
                printf( "建立日誌句柄失敗errno[%d]\n" , errno );
                return -1;
        }
        else
        {
                printf( "建立日誌句柄成功\n" );
        }
        /* 設置日誌輸出文件名 */
        SetLogOutput( g , LOG_OUTPUT_FILE , "test_LOGS.log" , LOG_NO_OUTPUTFUNC );
        /* 設置當前日誌過濾等級 */
        SetLogLevel( g , LOG_LEVEL_INFO );
        /* 設置當前行日誌風格方案 */
        SetLogStyles( g , LOG_STYLES_DOG , LOG_NO_STYLEFUNC);
        /* 剛剛建立的日誌句柄加到日誌句柄集合中 */
        AddLogToLogs( gs , "file" , g );
        
        /* 建立日誌句柄 */
        g = CreateLogHandle() ;
        if( g == NULL )
        {
                printf( "建立日誌句柄失敗errno[%d]\n" , errno );
                return -1;
        }
        else
        {
                printf( "建立日誌句柄成功\n" );
        }
        /* 設置日誌輸出文件名 */
        SetLogOutput( g , LOG_OUTPUT_STDOUT , NULL , LOG_NO_OUTPUTFUNC );
        /* 設置當前日誌過濾等級 */
        SetLogLevel( g , LOG_LEVEL_ERROR );
        /* 設置線程私有標籤 */
        SetLogCustLabel( g , 1 , "COREIB1" );
        /* 設置當前行日誌風格方案 */
        SetLogStyles( g , LOG_STYLES_EVENT , LOG_NO_STYLEFUNC);
        /* 剛剛建立的日誌句柄加到日誌句柄集合中 */
        AddLogToLogs( gs , "stdout" , g );
        
        /* 以不一樣日誌等級寫行日誌集合 */
        DEBUGLOGSG( "hello DEBUG" ); /* 這行日誌因等級不夠,被華麗的過濾了 */
        INFOLOGSG( "hello INFO" );
        WARNLOGSG( "hello WARN" );
        ERRORLOGSG( "hello ERROR" );
        FATALLOGSG( "hello FATAL" );
        
        /* 以不一樣日誌等級寫十六進制塊日誌集合 */
        DEBUGHEXLOGSG( buffer , buflen , "hello DEBUG buffer[%ld]" , buflen ); /* 又一個被華麗的過濾 */
        INFOHEXLOGSG( buffer , buflen , "hello INFO buffer[%ld]" , buflen );
        WARNHEXLOGSG( buffer , buflen , "hello WARN buffer[%ld]" , buflen );
        ERRORHEXLOGSG( buffer , buflen , "hello ERROR buffer[%ld]" , buflen );
        FATALHEXLOGSG( buffer , buflen , "hello FATAL buffer[%ld]" , buflen );
        
        /* 銷燬日誌句柄集合 */
        DestroyLogsHandleG(); /* 日誌句柄集合內包含的兩個日誌句柄連帶銷燬掉 */
        printf( "釋放日誌句柄集合\n" );
        
        return 0;
}

int main()
{
        return -test_LOGS();
}
編譯、連接、執行

$ gcc -g -fPIC -Wall -Werror -O2 -I. -std=c99 -I/home/calvin/exinc/iLOG3  -c test_LOGS.c
$ gcc -g -fPIC -Wall -Werror -O2 -o test_LOGS test_LOGS.o -L. -std=c99 -L/home/calvin/exlib -liLOG3
$ ./test_LOGS
建立日誌句柄集合成功
建立日誌句柄成功
建立日誌句柄成功
2014-02-10 00:35:54.807915 | COREIB1 | hello ERROR
2014-02-10 00:35:54.808017 | COREIB1 | hello FATAL
2014-02-10 00:35:54.808750 | COREIB1 | hello ERROR buffer[64]
            0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F    0123456789ABCDEF
0x00000000   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000010   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000020   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000030   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
2014-02-10 00:35:54.809138 | COREIB1 | hello FATAL buffer[64]
            0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F    0123456789ABCDEF
0x00000000   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000010   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000020   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000030   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
釋放日誌句柄集合
$ cat test_LOGS.log
2014-02-10 00:36:52.250602 | INFO  | 2300:3086878416:test_LOGS.c:71 | hello INFO
2014-02-10 00:36:52.251233 | WARN  | 2300:3086878416:test_LOGS.c:72 | hello WARN
2014-02-10 00:36:52.251246 | ERROR | 2300:3086878416:test_LOGS.c:73 | hello ERROR
2014-02-10 00:36:52.251568 | FATAL | 2300:3086878416:test_LOGS.c:74 | hello FATAL
2014-02-10 00:36:52.251646 | INFO  | 2300:3086878416:test_LOGS.c:78 | hello INFO buffer[64]
            0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F    0123456789ABCDEF
0x00000000   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000010   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000020   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000030   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
2014-02-10 00:36:52.252086 | WARN  | 2300:3086878416:test_LOGS.c:79 | hello WARN buffer[64]
            0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F    0123456789ABCDEF
0x00000000   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000010   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000020   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000030   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
2014-02-10 00:36:52.252129 | ERROR | 2300:3086878416:test_LOGS.c:80 | hello ERROR buffer[64]
            0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F    0123456789ABCDEF
0x00000000   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000010   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000020   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000030   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
2014-02-10 00:36:52.252612 | FATAL | 2300:3086878416:test_LOGS.c:81 | hello FATAL buffer[64]
            0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F    0123456789ABCDEF
0x00000000   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000010   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000020   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000030   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
你以爲調用函數來構建日誌句柄太煩了,但願用配置文件,沒問題,iLOG3自帶了一個簡單配置文件格式,看

hello_logsconf.conf git

id		hello
output		FILE	test_logconf.log
level		INFO
styles		DATETIME|LOGLEVEL|PID|TID|SOURCE|FORMAT|NEWLINE
options		CHANGE_TEST
rotate_mode	SIZE
rotate_size	10MB
log_bufsize	1MB	 5MB

id		stdout
output		STDOUT
level		INFO
custlabel1	COREIB1
styles		DATETIME|CUSTLABEL1|FORMAT|NEWLINE
下面不提供完整代碼了,看

#include "LOGSCONF.h"

int test_logsconf()
{
	LOGS		*gs = NULL ;
	
	gs = CreateLogsHandleFromConfig( "hello_logsconf.conf" , NULL ) ;
	SetGlobalLOGS( gs );
	
	/* 這裏就能刷刷刷的寫日誌了,其效果和上一個例子相同 */
	...
	
	return 0;
}
什麼,你嫌配置文件格式太難看了,我另外寫了一個姐妹函數庫iLOG3CONF_SML,用SML標記語言來配置LOGS,給個我在其它產品中的示例

hetao
{
	logs
	{
		log ( id = access )
		{
			output = FILE ;
			filename = "$HOME$/log/access.log" ;
			level = DEBUG ;
			styles = "DATETIME|LOGLEVEL|PID|TID|FORMAT|NEWLINE" ;
			rotate_mode = SIZE ;
			rotate_size = 10MB ;
		}
		
		log ( id = error )
		{
			output = FILE ;
			filename = "$HOME$/log/error.log" ;
			level = ERROR ;
			styles = "DATETIME|LOGLEVEL|SOURCE|FORMAT|NEWLINE" ;
			rotate_mode = SIZE ;
			rotate_size = 10MB ;
		}
	}
	
	module
	{
		connection ( filename = "$HOME$/so/hetao_module_connection_epoll.so" )
		{
		}
		
		protocol ( filename = "$HOME$/so/hetao_module_protocol_http.so" )
		{
			max_header_size = 10KB ;
			
			root = "$HOME$/www" ;
			index_page = "index.html" ;
			error_pages
			{
				error_page { error = 403 ; page = "$HOME$/www/403.html" } ;
				error_page { error = 404 ; page = "$HOME$/www/404.html" } ;
				error_page { error = 500 ; page = "$HOME$/www/500.html" } ;
				error_page { error = 505 ; page = "$HOME$/www/505.html" } ;
			}
		}
	}
	
	server
	{
		listen_ip = "127.0.0.1" ;
		listen_port = 8080 ;
		max_connections = 1024 ;
	}
}
代碼中這樣寫就能從配置中構建LOGS

LOGS	*gs = NULL ;
gs = CreateLogsHandleFromConfig_SML( "hetao.conf" , "/hetao/logs" , NULL ) ;
你問性能咋樣啊?我拿目前同類日誌函數庫作了性能測試,目前iLOG3是最快的。具體可參見源碼包中的用戶指南文檔中的性能比較章節。

是否是越看越心動了?那就趕忙下載來玩玩吧。 shell

首頁傳送門 : [url]http://git.oschina.net/calvinwilliams/iLOG3[/url]
源代碼包doc目錄中包含了用戶指南和參考手冊,裏面有更詳盡的說明
安全

相關文章
相關標籤/搜索