Log4delphi使用心得

log4delphi试用

因为delphi不是我的主力开发工具,所有一直没有使用一个正式的日志组件。
偶尔要记日志时,就复制同事的一个简单的文件日志函数。
现在又要用到delphi日志了,决定找个通用的日志组件,造福共事的Delphi程序员们。

让我失望的是,日志功能好像对Delphi程序员没什么吸引力,
百度“Delphi 日志”竟然没有什么有用线索。还是Google“Delphi logger”有点用。

不管怎样,让我找到了log4delphi。明显国内用的人不多,不知大家是否有更好的日志类。
对我来说,log4delphi与log4j、log4cpp如出一辙,正合我意。
0.7版,近两年没更新了。看SVN也是没有任何更新。
下载了看,文档相当全。


因为用D6,而bin包只有D7的,所以自己需要编译一个包。编译时注意:
 
  * 有STD和PROF两个版本的*.dpk,比较一下,STD没有RollingAppender,看来PROF全一点。
  * 参考编译出错信息,需手工创建build目录。
  * 编译报util/TFileUnit文件未找到,直接删了它就好了,没用。

可能用它自带的Makefile更快更好,但好像Makefile是对D7的,也要改。
顺便安装包,并添加lib目录。

DELPHI盒子网站上有个log4Delphi v0.7 修改版,据称发现并改正了内存泄漏。
http://www.2ccc.com/article.asp?articleid=3900
我也下载查看了,觉得没改全,发了个评论。决定暂时用原版。

接下来就可以按照它的Get Started和Tutorial试用了。

Get Started例子:

日志文件在写时,无法共享读取,不能实时查看日志。
日志文件名必须是完整路径,不能仅是文件名,也不能‘./test.log’这样。
TFileAppender创建时会清空文件,而不是Append。

Tutorial例子:

TConfiguratorUnit.doPropertiesConfiguration('log4delphi.properties');
同样使用TFileAppender时却没有打开日志文件时的共享违例。

仅配置rootLogger,没有配置subLogger时,subLogger无输出。与log4j不同。

 

 

转载自:http://blog.youkuaiyun.com/brightgems/archive/2006/06/19/814042.aspx

 

Log4d是apache下的一个delphi开源子项目,它的设计思想来源于Log4j,但并不是Log4j的子项目,主要目标是开发环境与生产环境下的日志输出。

一、下载
https://sourceforge.net/project/showfiles.php?group_id=145326
二、安装
将源代码下的log4delphi\src\delphi\log4delphi_D6.dpk包安装在IDE下。
三、基本使用方法
1.在dpr文件的source 中创建Logger实例(TConfiguratorUnit.doBasicConfiguration)
如:
  Application.Initialize;
//使用运行期默认配置,输出日志文件名是'log4delphi.log’
  TConfiguratorUnit.doBasicConfiguration;
  Application.CreateForm(TForm1, Form1);
  Application.Run;  
2.配置Logger
var
   logger : TLogger;
begin
   logger := TLogger.getInstance;
   logger.setLevel(TLevelUnit.INFO);
   logger.addAppender(TFileAppender.Create('C:\test.log'));  
3.在你需要的地方写Log信息
根据Level的类型,有五种类别的Log信息
logger.debug('Debug message');
   logger.info('Info message');
   logger.warn('Warn message');
   logger.error('Error message');
   logger.fatal('Fatal message');
4.释放Logger实例
Finalization
    TLogger.freeInstances;
四、更深入的介绍
Log4d由五个核心的components组成:Levels, LoggingEvents, Layouts, Appenders and Loggers.
1. Levels。每一个Log event 都有一个优先级,Levels就是用来表示优先级的。因此,每一个优先级其实就是一个数值常量,可用于比较。
Level有以下几种:
TLevelUnit.OFF
  TLevelUnit.FATAL
  TLevelUnit.ERROR
  TLevelUnit.WARN
  TLevelUnit.INFO
  TLevelUnit.DEBUG
  TLevelUnit.ALL
2.LoggingEvents.当产生一个Log信息或Logger实例创建时发生。
Logging 包含的重要信息有:发生时间,消息内容,已经发生的异常及优先级。
3. Layouts.它负责LoggingEvents的格式化输出样式。
The TLayout 有以下方法:
  function format(event : TLoggingEvent) : String; Virtual; Abstract;
  function getContentType() : String; Virtual;
  function getHeader() : String; Virtual;
  function getFooter() : String; Virtual;
  function ignoresException() : Boolean; Virtual;
常用的Layout有:
l TSimpleLayout
输出内容如:DEBUG - Button Clicked
l TPatternLayout.它为格式化输出提供了更多的控制。格式化的模式与Format函数相似,即以%开头,接着跟修饰符和转换符。如:
Pattern="%d [%5p] %m%n"
产生的输出是
12/20/2005 4:53:33 PM [DEBUG] Debug message
12/20/2005 4:53:33 PM [ INFO] Info message
12/20/2005 4:53:33 PM [ WARN] Warn message
12/20/2005 4:53:33 PM [ERROR] Error message
12/20/2005 4:53:33 PM [FATAL] Fatal message
含义: %d 日期
 %m 消息内容
 %n 换行
 %p 优先级
 %e 异常的类名与message
 %L Logger的名称
4. Appenders.表示输出的目的是控制台,文件,还是数据库。
常用的有TFileAppender, TDBAppender

五、配置文件
1.程序里加载配置文件
Application.Initialize;
  TConfiguratorUnit.doPropertiesConfiguration('log4delphi.properties'); 
  Application.CreateForm(TForm1, Form1);
  Application.Run; 


2.写配置文件'log4delphi.properties'
l 控制输出的信息类别
# Set this to true to turn on Log4Delphi's internal
# logging
log4delphi.debug=false 
log4delphi.info=false 
log4delphi.all=true
l Root Logger
# Set the root logger's priority threshold to DEBUG and assign an 
# appender named "fileAppender" to it.
log4delphi.rootLogger=DEBUG, fileAppender
l 配置Appender
# Specify the appender class for fileAppender.
log4delphi.appender.fileAppender=TFileAppender
    
# Specify which file fileAppender should use.
log4delphi.appender.fileAppender.File=app.log
l 设置Layout
# Specify the layout class for fileAppender.
log4delphi.appender.fileAppender.layout=TSimpleLayout  
# Use TPattern layout
log4delphi.appender.fileAppender.layout=TPatternLayout
log4delphi.appender.fileAppender.layout.pattern=%d [%5p] %m%n

 


本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/brightgems/archive/2006/06/19/814042.aspx

 

上面都是参考资料,下面是我自己使用过程中使用的过程:

1:安装PROF这个版本,通过文件对比可看出该版本应用的文件多点,可能会更好(猜的)。

2:添加源码以及dcu路径。(在工具->环境选项->Library path中加入该两个路径:“src\delphi”、“build”)。

3:在Application.Initialize;的后面调用doPropertiesConfiguration('log4delphi.properties'); 去读取配置并初始化log4。(注意,该方法在TConfiguratorUnit单元中,需要use该单元)

4:将log4delphi.properties放入应用程序同一目录下。log4delphi.properties可从下载包中得到。

5:调用log4的记录方法:TLogger.getInstance.debug('Button Clicked!');(需要引入TLoggerUnit单元)。

执行的话基本上都能在程序所在的目录下有个*.log文件。

6:释放掉TLogger的对象:在不用TLogger对象时释放:TLogger.freeInstances;(一般在程序退出的时候要把该对象释放掉)

有关配置文件中一个要注意的地方:

 

代码

 

这样配置才能把时间按照{}的格式进行日志输出。由于该log4delphi的配置资料基本上没有,因此,该配置需要看源码才能知道有哪些配置该怎么设置。目前我还不知道如何让日志文件按照时间格式来自动生成出来,我怀疑,它会根据设置的容量,自动把历史数据保存到另外一个以保存日期为名称的文件。有待日后验证。

 

今天早上测试了下,发现有如下一个配置:

 

复制代码
代码
#定义日志记录的类型
#log4delphi.appender.fileAppender
= TFileAppender
log4delphi.appender.fileAppender
= TRollingFileAppender
log4delphi.appender.fileAppender.MaxBackupIndex
= 20
log4delphi.appender.fileAppender.MaxFileSize
= 3M
log4delphi.appender.fileAppender.File
= app.log
log4delphi.appender.fileAppender.AppDir
= true
log4delphi.appender.fileAppender.Append
= true
复制代码

 

fileAppender=TRollingFileAppender这个配置才会实现超出MaxFileSize时,会把日志根据大小自动分割后保存到后缀为*.log.1、*.log.2类似的文件。如果没猜错,MaxBackupIndex这个属性应该是*.log.?这个?的值了。

日志组件log4delphilog4j、log4cpp如出一辙 1.安装:log4Delphi无需安装,直接解压包解压后放入任意目录(我的目录是:'D:/3rdlib/delphi/log4delphi-0.7)即可。 2.使用:在工程文件中引用解压包中src目录下所有的*.pas文件,如下: uses Forms, Unit1 in 'Unit1.pas' {Form1}, TAppenderUnit in 'D:/3rdlib/delphi/log4delphi-0.7/src/delphi/TAppenderUnit.pas', TBDELogInserterUnit in 'D:/3rdlib/delphi/log4delphi-0.7/src/delphi/TBDELogInserterUnit.pas', TConfiguratorUnit in 'D:/3rdlib/delphi/log4delphi-0.7/src/delphi/TConfiguratorUnit.pas', TConsoleUnit in 'D:/3rdlib/delphi/log4delphi-0.7/src/delphi/TConsoleUnit.pas' {TConsole}, TDBAppenderUnit in 'D:/3rdlib/delphi/log4delphi-0.7/src/delphi/TDBAppenderUnit.pas', TDBLogInserterUnit in 'D:/3rdlib/delphi/log4delphi-0.7/src/delphi/TDBLogInserterUnit.pas', TDBXLogInserterUnit in 'D:/3rdlib/delphi/log4delphi-0.7/src/delphi/TDBXLogInserterUnit.pas', TErrorHandlerUnit in 'D:/3rdlib/delphi/log4delphi-0.7/src/delphi/TErrorHandlerUnit.pas', TFileAppenderUnit in 'D:/3rdlib/delphi/log4delphi-0.7/src/delphi/TFileAppenderUnit.pas', THTMLLayoutUnit in 'D:/3rdlib/delphi/log4delphi-0.7/src/delphi/THTMLLayoutUnit.pas', TIBXLogInserterUnit in 'D:/3rdlib/delphi/log4delphi-0.7/src/delphi/TIBXLogInserterUnit.pas', TLayoutUnit in 'D:/3rdlib/delphi/log4delphi-0.7/src/delphi/TLayoutUnit.pas', TLevelUnit in 'D:/3rdlib/delphi/log4delphi-0.7/src/delphi/TLevelUnit.pas', TLoggerUnit in 'D:/3rdlib/delphi/log4delphi-0.7/src/delphi/TLoggerUnit.pas', TLoggingEventUnit in 'D:/3rdlib/delphi/log4delphi-0.7/src/delphi/TLoggingEventUnit.pas', TLogLogUnit in 'D:/3rdlib/delphi/log4delphi-0.7/src/delphi/TLogLogUnit.pas', TNullAppenderUnit in 'D:/3rdlib/delphi/log4delphi-0.7/src/delphi/TNullAppenderUnit.pas', TOnlyOnceErrorHandlerUnit in 'D:/3rdlib/delphi/log4delphi-0.7/src/delphi/TOnlyOnceErrorHandlerUnit.pas', TOptionConverterUnit in 'D:/3rdlib/delphi/log4delphi-0.7/src/delphi/TOptionConverterUnit.pas', TPatternLayoutUnit in 'D:/3rdlib/delphi/log4delphi-0.7/src/delphi/TPatternLayoutUnit.pas', TPropert
Delphi Logger { 超简单实用的DELPHI日志单元 1.0.0 优化版 引用本单元即可使用 一共四个方法 procedure log4error(msg: AnsiString); //写ERROR级别的日志 procedure log4info(msg: AnsiString); //写INFO级别的日志 procedure log4debug(msg: AnsiString); //写DEBUG级别的日志 function log4filename():AnsiString; //得到当前日志文件全名 一个配置文件 log4me.ini #配置文件和主程序在同一目录.没有这个文件或不在主目录中则不写日志 [log4me] #path,日志的存放目录.必须是主程序目录及子目录. #例子:主程序目录 #path=. #例子:子目录 #path=temp\logs path=logs #level,日志等级,只能是 error,info,debug之一 #为error时,只有log4error打印的日志被输出. #为info时,log4error和log4info打印的日志被输出. #为debug时,log4error,log4info,log4debug打印的日志都被输出. level=info 一个可选工具 tail.exe 命令行中输入 >tail.exe -1000f 日志文件名 即可动态查看日志输出 或用程序调用 var cmd :AnsiString; log_file:AnsiString; begin log_file := log4filename(); //得到当前日志文件全名 cmd := ExtractFilePath(ParamStr(0)) + 'tail.exe -1000f "'+ log_file +'"'; WinExec(PAnsiChar(cmd),SW_SHOWNORMAL); //程序调用 tail.exe工具来查看日志 } unit log4me; interface uses classes, sysutils, ComObj, windows,IniFiles; procedure log4error(msg: AnsiString); //写ERROR级别的日志 procedure log4info(msg: AnsiString); //写INFO级别的日志 procedure log4debug(msg: AnsiString); //写DEBUG级别的日志 function log4filename():AnsiString; //得到当前日志文件全名 var log_filename: AnsiString; //日志文件全名 implementation var log_ThreadLock: TRTLCriticalSection; // 临界区 log_fileStream: TFileStream; log_filepath: AnsiString; //日志文件路径 log_initime:TDateTime; log_doerror, log_dodebug, log_doinfo: Boolean; procedure log_init(); var tmpStr:String; begin log_doerror := False; log_dodebug := False; log_doinfo := False; if FileExists(ExtractFilePath(ParamStr(0)) + 'log4me.ini') then begin with TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'log4me.ini') do try log_filepath := ExtractFilePath(ParamStr(0)) + '\' + ReadString('log4me','path','logs') + '\'; tmpStr := LowerCase(ReadString('log4me','level','info')); log_doerror := (tmpStr = 'debug') or (tmpStr = 'info') or (tmpStr = 'error'); log_doinfo := (tmpStr = 'debug') or (tmpStr = 'info'); log_dodebug := (tmpStr = 'debug') ; finally Free; end; end; log_initime := Now; end; procedure log4me_addLog(filename: AnsiString; p: PAnsiChar); var fmode :Word; tmp:AnsiString; begin //进入临界区,多线程时可以保护资源 EnterCriticalSection(log_ThreadLock); try try //如果要写的日志文件和打开的不同(在程序第一次运行和跨天的时候出现) //则关闭打开的日志文件。 if filename log_filename then begin log_filename := filename; if Assigned(log_fileStream) then begin log_fileStream.Free; log_fileStream := nil; end; end; //如果要写的日志文件没有打开(在程序第一次运行和跨天的时候出现) //则打开日志文件。 if not Assigned(log_fileStream) then begin if FileExists(log_filename) then fmode := fmOpenWrite or fmShareDenyNone else fmode := fmCreate or fmShareDenyNone ; log_fileStream := TFileStream.Create(log_filename,fmode); log_fileStream.Position := log_fileStream.Size; end; //在日志文件中写入日志 log_fileStream.Write(p^, strlen(p)); except on E:Exception do begin try tmp := ExtractFilePath(ParamStr(0)) + 'log4me_err.log'; if FileExists(tmp) then fmode := fmOpenWrite or fmShareDenyNone else fmode := fmCreate or fmShareDenyNone ; with TFileStream.Create(tmp, fmode) do begin Position := Size; tmp := FormatDateTime('yyyy-mm-dd hh:nn:ss.zzz', Now) + ' ' + E.Message + #13#10; Write(tmp[1],Length(tmp)); Free; end; except end; end; end; finally //无论如何,离开临界区 LeaveCriticalSection(log_ThreadLock); end; end; procedure log4write(msg: AnsiString); var strline: AnsiString; begin // 最多每秒重加载一次配置文件 if (Now() - log_initime) > (1/(24*60*60)) then log_init(); //日志开头加时间 strline := FormatDateTime('hh:nn:ss.zzz', Now) + ' ' + msg + #13#10; //写到当天的日志文件中 log4me_addLog(log_filepath + FormatDateTime('yyyy-mm-dd', Now) + '.log', PAnsiChar(strline)); end; //-----下面4个是对外方法------------------------- function log4filename():AnsiString; begin Result := log_filename; end; procedure log4error(msg: AnsiString); begin if log_doerror then log4write('[error]' + msg); end; procedure log4info(msg: AnsiString); begin if log_doinfo then log4write('[info ]' + msg); end; procedure log4debug(msg: AnsiString); begin if log_dodebug then log4write('[debug]' + msg); end; // ----------- 类初始化 -------------// initialization InitializeCriticalSection(log_ThreadLock); log_init; log4info('log4me:application starting....'); // ----------- 类销毁 -------------// finalization log4info('log4me:application stoping....'); DeleteCriticalSection(log_ThreadLock); if Assigned(log_fileStream) then log_fileStream.Free; end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值