iLOG3 是一个轻便易用、概念简单,高性能、多层接口、原生跨平台、(规范使用时)线程安全的遵循LGPL开源协议的标准 C 日志函数库。
基本特性如下:
原生跨平台,这意味着你的软件在日志层面上是可轻松移植的,目前支持WINDOWS & UNIX & Linux ,iLOG3会在不同的操作系统上做相应的实现和优化
五类日志等级
变参的日志函数和日志宏
行日志风格方案选配
输出介质有文件、标准输出、标准错误输出、syslogd或WINDOWS EVENT、自定义介质
高级特性如下:
支持日志选项组合
支持按日志文件大小、每天、每小时转档
支持行日志风格自定义回调函数,很容易定制自己的行日志格式
支持日志文件的打开、输出、关闭自定义回调函数,很容易扩展成日志输出到远程日志服务器落地
线程安全、简易MDC、基于线程本地存储的缺省全局日志句柄
分层实施“日志句柄层(LOG)->日志句柄集合层(LOGS)->配置文件接口层(LOGCONF、LOGSCONF)”。其实大部分用户的日志需求很简单,一个进程写一个日志文件(使用日志句柄层函数即可),但也考虑到另外一些用户有多个输出对象需求(使用日志句柄集合层函数即可),还有用户喜欢用外部配置文件来配置日志(使用配置文件接口层函数即可),不同用户在不同项目场景中使用iLOG3的不同层接口,不至于杀鸡用牛刀、小刀砍大树。
我还开发了一个姐妹函数库iLOG3CONF_SML来支持用SML标记语言配置文件来配置日志句柄,有兴趣的朋友也可以调用日志句柄层或日志句柄集合层函数开发自己的iLOG3CONF_*,实现用XML或现在流行的json或自己项目统一配置文件格式,来实现用外部配置文件配置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_hello() { 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_iLOG3.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_hello(); }输出日志如下:
2014-02-09 20:06:39.203000 | INFO | 3880:700:test_20060920.c:32 | hello INFO 2014-02-09 20:06:39.203000 | WARN | 3880:700:test_20060920.c:33 | hello WARN 2014-02-09 20:06:39.203000 | ERROR | 3880:700:test_20060920.c:34 | hello ERROR 2014-02-09 20:06:39.203000 | FATAL | 3880:700:test_20060920.c:35 | hello FATAL 2014-02-09 20:06:39.203000 | INFO | 3880:700:test_20060920.c:39 | 缓冲区[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-09 20:06:39.203000 | WARN | 3880:700:test_20060920.c:40 | 缓冲区[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-09 20:06:39.203000 | ERROR | 3880:700:test_20060920.c:41 | 缓冲区[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-09 20:06:39.203000 | FATAL | 3880:700:test_20060920.c:42 | 缓冲区[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 ................
------------------------------------------------------------
压测硬件(2007年买的老爷机)
CPU : Intel Dual E2160 1.8GHz 1.81GHz
内存 : 2GB
硬盘 : 希捷 250GB 7200转
压测软件
Windows XP SP3 ( VMware 6.0 ( RedHat Enterprise Linux 5.4 分了256MB内存 ) )
压测场景
10个进程,每个进程开10个线程,每个线程写10000条日志
每行日志格式大致是”日期 时间 | PID:TID:源代码文件名:源行号 | loglog”
压测命令
$ time ./test_press_mpt 10 10 10000 ; wc *.log*
开压!
real 0m13.922s
user 0m1.676s
sys 0m12.211s
124671 997368 9100983 test_press_mpt.log
148650 1189200 10851450 test_press_mpt.log.1
143668 1149344 10487764 test_press_mpt.log.2
143657 1149256 10486961 test_press_mpt.log.3
150482 1203856 10985186 test_press_mpt.log.4
143699 1149592 10490027 test_press_mpt.log.5
145173 1161384 10597629 test_press_mpt.log.6
1000000 8000000 73000000 total
另外,在公司的PC SERVER也跑过,速度提高到real 6s左右
------------------------------------------------------------
源代码包中doc目录包含文档,文档目录如下
《iLOG3日志函数库用户指南.doc》
目录索引
1 前言 5
2 概述 5
3 编译安装 6
3.1 依赖库 6
3.2 用自带makefile或VC6工程文件编译安装 7
3.3 自己手动编译安装 9
4 基本使用 10
4.1 一点点概念 10
4.2 第一个示例 10
4.3 行日志风格方案选配 13
5 高级特性 14
5.1 设置日志选项 14
5.2 日志文件转档 14
5.3 自定义行日志风格 15
5.4 自定义日志输出类型 16
5.5 自定义日志的打开、输出、关闭 16
5.6 线程安全 18
5.6.1 MDC 18
5.6.2 基于线程本地存储的缺省全局日志句柄 19
5.7 一个常用示例 20
6 日志句柄集合层 21
7 配置文件接口层 24
7.1 自带的简单配置文件接口层 24
7.2 配置文件接口展望 26
8 源码分析 27
8.1 第一条线:日志句柄的创建销毁 28
8.2 第二条线:日志句柄的环境设置 29
8.3 第三条线:写日志 37
9 同类日志函数库比较 41
9.1 性能比较 41
9.2 功能比较 45
10 源代码包结构 47
《iLOG3日志函数库参考手册.doc》
目录索引
1 宏 6
1.1 错误码宏 6
1.2 日志输出类型宏 6
1.3 日志等级宏 6
1.4 行日志风格组合宏 7
1.5 日志选项组合宏 8
1.6 日志转档模式宏 8
2 日志句柄函数 9
2.1 管理日志句柄 9
2.1.1 创建日志句柄 9
2.1.2 销毁日志句柄 9
2.2 句柄环境设置 9
2.2.1 设置日志输出 9
2.2.2 设置当前日志过滤等级 10
2.2.3 设置行日志风格方案 10
2.3 高级句柄环境设置 11
2.3.1 设置日志句柄选项 11
2.3.2 设置自定义标签 11
2.3.3 设置日志转档模式 11
2.3.4 设置日志文件转档大小 12
2.3.5 设置日志文件转档大小的压迫系数 12
2.3.6 设置行日志缓冲区大小 12
2.3.7 设置十六进制块日志缓冲区大小 13
2.4 行日志输出 13
2.4.1 带日志等级的写行日志 13
2.4.2 写调试行日志 14
2.4.3 写普通信息行日志 14
2.4.4 写警告行日志 14
2.4.5 写错误行日志 15
2.4.6 写严重错误行日志 15
2.5 十六进制块日志输出 16
2.5.1 带日志等级的写十六进制块日志 16
2.5.2 写十六进制块调试日志 16
2.5.3 写十六进制普通信息块日志 17
2.5.4 写十六进制块警告日志 17
2.5.5 写十六进制块错误日志 18
2.5.6 写十六进制块严重错误日志 18
3 日志句柄集合函数 19
3.1 管理日志句柄集合 19
3.1.1 创建日志句柄集合 19
3.1.2 销毁日志句柄集合 19
3.2 管理日志句柄集合中的日志句柄 19
3.2.1 压入一个日志句柄到日志句柄集合中 19
3.2.2 从一个日志句柄集合中弹出一个指定标识的日志句柄 20
3.2.3 从一个日志句柄集合中查询一个指定标识的日志句柄 20
3.2.4 遍历一个日志句柄集合中所有日志句柄 20
4 配置文件接口层函数 21
4.1 日志句柄 21
4.1.1 从配置文件构建日志句柄 21
4.2 日志句柄集合 21
4.2.1 从配置文件构建日志句柄集合 21
5 配置辅助函数 22
5.1 属性转换函数 22
5.1.1 日志输出类型(字符串转换为整型) 22
5.1.2 日志等级类型(字符串转换为整型) 22
5.1.3 日志等级类型(整型转换为字符串) 22
5.1.4 行日志风格(字符串转换为整型) 23
5.1.5 日志选项(字符串转换为整型) 23
5.1.6 日志转档模式(字符串转换为整型) 23
5.1.7 日志缓冲区(字符串转换为整型) 24
6 简单配置文件属性列表 24
------------------------------------------------------------
欢迎使用,如果你碰到了使用问题或者有更酷的想法请告诉我,谢谢 ^_^
首页传送门
http://git.oschina.net/calvinwilliams/iLOG3
技术博客
《开源纯C日志函数库iLOG3快速入门(一、基本使用速览).txt》
http://my.oschina.net/u/988092/blog/198377
《开源纯C日志函数库iLOG3快速入门(二、定制远程日志服务).txt》
http://my.oschina.net/u/988092/blog/199698
《开源纯C日志函数库iLOG3快速入门(三、日志过滤和转档后压缩)》
http://my.oschina.net/u/988092/blog/200005
《开源纯C日志函数库iLOG3快速入门(四、使用合适的日志输出函数或宏)》
http://my.oschina.net/u/988092/blog/200013
《开源纯C日志函数库iLOG3快速入门(五、与随手写的简单写日志函数的比较)》
http://my.oschina.net/u/988092/blog/202240http://
《开源纯C日志函数库iLOG3快速入门(六、日志配置文件)》
http://my.oschina.net/u/988092/blog/203743
《开源纯C日志函数库iLOG3快速入门(七、一份配置应用于多个日志文件)》
http://my.oschina.net/u/988092/blog/265787
《开源纯C日志函数库iLOG3快速入门(八、如果你喜欢简单日志函数甚于日志函数库)》
http://my.oschina.net/u/988092/blog/293142
这个封装类是为了不用跟傻X扯逼而创造的....... 首先下载个iLog3,好吧,重点不是日志类,喜欢的话,其他日志类也可以,原理是生成一个console窗口,然后把日志信息输出到console里面,这样做的好处在于在非DEBUG情况下可以实时观察到控件的执行情况,尤其在插件开发中,不用跟java那边扯逼 vs2010+unicode CLog.h #pragma once // /*这是通过iL
我正在学习面向对象的C,并有一个关于虚拟/纯虚拟和多级继承的问题。 假设我有这样的简单代码: 我的理解是,除非getWidth被指定为虚拟,否则多态将使用“Base”类的函数。我的意思是r-的最终调用 在这种情况下,我注意到如果我删除Shape中的纯虚拟声明,我们会得到我刚才描述的行为。在基类中有一个纯虚函数会自动使该函数的所有定义都是虚的吗?
什么是纯函数? 在函数式编程里我们会经常谈到这两个概念。一个是 纯函数。另一个是 附加作用(副作用)。这里我们就结合实际来介绍一下 纯函数 和 附加作用。 下面我们给出两个函数 increaseA 和 increaseB,他们其中一个是 纯函数,另一个不是 纯函数: var state = 0 func increaseA() { state += 1 } increaseA() p
在 C++中,可以将虚函数声明为纯虚函数,语法格式为: virtual 返回值类型 函数名 (函数参数) = 0; 纯虚函数没有函数体,只有函数声明,在虚函数声明的结尾加上 ,表明此函数为纯虚函数。 最后的 并不表示函数返回值为0,它只起形式上的作用,告诉编译系统“这是纯虚函数”。 包含纯虚函数的类称为抽象类(Abstract Class)。之所以说它抽象,是因为它无法实例化,也就是无法创建对象。
我正在使用一组持久的函数来完成一些关键的后端逻辑和操作,我希望它们在同一个文件中写入日志,这样我就可以进行更好的分析。对了,我知道我正在使用log.information方法注入的ILog实例,但是每个函数都编写自己的日志文件。 我也在使用application insights,但由于遥测采样,文件中的信息比application insights要多得多。 以下是我的host.json文件的示
本文向大家介绍C++中虚函数与纯虚函数的用法,包括了C++中虚函数与纯虚函数的用法的使用技巧和注意事项,需要的朋友参考一下 本文较为深入的分析了C++中虚函数与纯虚函数的用法,对于学习和掌握面向对象程序设计来说是至关重要的。具体内容如下: 首先,面向对象程序设计(object-oriented programming)的核心思想是数据抽象、继承、动态绑定。通过数据抽象,可以使类的接口与实现分离,使
如果一个函数的返回结果只取决于参数值,并且没有像修改参数、输出一些值等副作用,那么就可认为此函数是纯函数。 下面这个after函数就是一例。此函数比较两个Time变量并返回一个布尔值并指出第一个操作数是否比第二个晚: bool after (Time& time1, Time& time2) { if (time1.hour > time2.hour) return true; i