unit uProgLog;

interface

uses
Windows, SysUtils, SyncObjs; const
C_LOG_LEVEL_TRACE = $;
C_LOG_LEVEL_WARNING = $;
C_LOG_LEVEL_ERROR = $;
type
EnumSeverity = (TraceLevel, WarningLevel, ErrorLevel, LogLevel); function SeverityDesc(severity: EnumSeverity): string; type
TLogFile = class
private
FLogKeepDays: Integer; //日志保存时间
FLogLevel: DWORD; //日志级别
FLogPath: string; //日志保存路径,以"\"结尾
FLogAppName: string; //应用程序名(日志文件前缀) FCsWriteLogFile: TCriticalSection;
FLogFile: TextFile; //日志文件句柄
FLogOpened: Boolean; //日志文件是否打开
FFileTimeStamp: TTimeStamp; //当前日志文件创建或打开时间 function GetLogKeepDays(): Integer;
procedure SetLogKeepDays(days: Integer);
function GetLogLevel(): DWORD;
procedure SetLogLevel(level: DWORD);
function GetLogPath(): string;
procedure SetLogPath(path: string);
function GetLogAppName(): string;
procedure SetLogAppName(name: string);
protected
function WriteLogFile(const szFormat: string; const Args: array of const): Boolean;
public ////////////////////////////////////////////////////////////////////////////
//Procedure/Function Name: Trace()
//Describe: 记录日志到日志文件。如果日志文件路径不存在,会自动创建。如果日志文件不存在,
// 则创建相应的日志文件;如果日子文件已存在,则打开相应的日志文件,并将日志添加到文件结尾。
//Input : severity: 日志级别。根据日志级别参数决定该级别日志是否需要保存,
// 但LogLevel级别的日志不受日志级别参数影响,都保存到了日志文件。
// subject: 模块名称。
// desc: 日志内容。
//Result : N/A
//Catch Exception: No
////////////////////////////////////////////////////////////////////////////
procedure Trace(severity: EnumSeverity; const subject, desc: string); overload; ////////////////////////////////////////////////////////////////////////////
//Procedure/Function Name: Trace()
//Describe: 记录日志到日志文件。如果日志文件路径不存在,会自动创建。如果日志文件不存在,
// 则创建相应的日志文件;如果日子文件已存在,则打开相应的日志文件,并将日志添加到文件结尾。
//Input : severity: 日志级别。根据日志级别参数决定该级别日志是否需要保存,
// 但LogLevel级别的日志不受日志级别参数影响,都保存到了日志文件。
// subject: 模块名称。
// descFormat: 包含格式化信息的日志内容。
// Args: 格式化参数数组。
//Result : N/A
//Catch Exception: No
////////////////////////////////////////////////////////////////////////////
procedure Trace(severity: EnumSeverity; const subject, descFormat: string; const Args: array of const); overload; ////////////////////////////////////////////////////////////////////////////
//Procedure/Function Name: DeleteLogFile()
//Describe: 删除超过保存期限的日志文件。在日志文件路径中搜索超过保存期限的日志,将之删除。
// 该方法只需在应用程序启动时调用一次,以删除超过保存期限的日志。
//Input : N/A
//Result : Boolean 成功返回TRUE,失败返回FALSE
//Catch Exception: No
////////////////////////////////////////////////////////////////////////////
function DeleteLogFile(): Boolean; constructor Create();
Destructor Destroy(); override; property LogKeepDays: Integer read GetLogKeepDays write SetLogKeepDays;
property Level: DWORD read GetLogLevel write SetLogLevel;
property LogPath: string read GetLogPath write SetLogPath;
property LogAppName: string read GetLogAppName write SetLogAppName;
end; function BooleanDesc(Value : Boolean): string; implementation uses Forms, SqlTimSt; function BooleanDesc(Value : Boolean): string;
begin
if Value then Result := 'TRUE'
else Result := 'FALSE';
end; function SeverityDesc(severity: EnumSeverity): string;
begin
if (severity = ErrorLevel) then result := 'X'
else if (severity = WarningLevel) then result := '!'
else result := ' ';
end; { TLogFile } constructor TLogFile.Create;
begin
FLogOpened := False;
FCsWriteLogFile := TCriticalSection.Create; FLogKeepDays := ;
FLogLevel := C_LOG_LEVEL_TRACE or C_LOG_LEVEL_WARNING or C_LOG_LEVEL_ERROR;
FLogPath := ExtractFilePath(Application.ExeName) + 'Log\';
FLogAppName := ChangeFileExt(ExtractFileName(Application.ExeName),'');
end; function TLogFile.DeleteLogFile(): Boolean;
var
rc : DWORD;
SearchRec: TSearchRec;
bResult: Boolean;
FileMask: string;
LocalFileTime: TFileTime;
FileTime: Integer;
begin
result := false;
rc := GetFileAttributes(PChar(FLogPath));
if (rc = $FFFFFFFF) or (FILE_ATTRIBUTE_DIRECTORY and rc = ) then exit; FileMask := FLogPath + FLogAppName + '*.log';
bResult := FindFirst(FileMask, faAnyFile, SearchRec) = ;
try
if bResult then
begin
repeat
if (SearchRec.Name[] <> '.') and
(SearchRec.Attr and faVolumeID <> faVolumeID) and
(SearchRec.Attr and faDirectory <> faDirectory) then
begin
FileTimeToLocalFileTime(SearchRec.FindData.ftCreationTime, LocalFileTime);
FileTimeToDosDateTime(LocalFileTime, LongRec(FileTime).Hi, LongRec(FileTime).Lo);
// 按照文件创建日期删除文件
if FileDateToDateTime(FileTime) <= Now() - GetLogKeepDays() then
DeleteFile(FLogPath + SearchRec.Name);
end;
until FindNext(SearchRec) <> ;
end;
finally
FindClose(SearchRec);
end;
end; destructor TLogFile.Destroy;
begin
if (FLogOpened) then CloseFile(FLogFile);
FCsWriteLogFile.Free();
inherited;
end; function TLogFile.GetLogAppName: string;
begin
result := FLogAppName;
end; function TLogFile.GetLogKeepDays: Integer;
begin
result := FLogKeepDays;
end; function TLogFile.GetLogLevel: DWORD;
begin
result := FLogLevel;
end; function TLogFile.GetLogPath: string;
begin
result := FLogPath;
end; procedure TLogFile.SetLogAppName(name: string);
begin
FLogAppName := ChangeFileExt(name, '');
end; procedure TLogFile.SetLogKeepDays(days: Integer);
begin
FLogKeepDays := days;
end; procedure TLogFile.SetLogLevel(level: DWORD);
begin
FLogLevel := level;
end; procedure TLogFile.SetLogPath(path: string);
begin
if Trim(path) = '' then exit;
if path[Length(path)] <> '\' then FLogPath := path + '\'
else FLogPath := path;
end; procedure TLogFile.Trace(severity: EnumSeverity; const subject, desc: string);
begin
// 根据配置的日志级别决定是否写日志
if ((severity = LogLevel) or
((severity = ErrorLevel) and (FLogLevel and C_LOG_LEVEL_ERROR = C_LOG_LEVEL_ERROR)) or
((severity = WarningLevel) and (FLogLevel and C_LOG_LEVEL_WARNING = C_LOG_LEVEL_WARNING)) or
((severity = TraceLevel) and (FLogLevel and C_LOG_LEVEL_TRACE = C_LOG_LEVEL_TRACE))) then
begin
WriteLogFile('%s @@ %s @ %s $ %s', [SeverityDesc(severity), FLogAppName, subject, desc]);
end;
end; procedure TLogFile.Trace(severity: EnumSeverity; const subject,
descFormat: string; const Args: array of const);
var
desc: string;
begin
// 根据配置的日志级别决定是否写日志
if ((severity = LogLevel) or
((severity = ErrorLevel) and (FLogLevel and C_LOG_LEVEL_ERROR = C_LOG_LEVEL_ERROR)) or
((severity = WarningLevel) and (FLogLevel and C_LOG_LEVEL_WARNING = C_LOG_LEVEL_WARNING)) or
((severity = TraceLevel) and (FLogLevel and C_LOG_LEVEL_TRACE = C_LOG_LEVEL_TRACE))) then
begin
desc := Format(descFormat, Args);
WriteLogFile('%s @@ %s @ %s $ %s', [SeverityDesc(severity), FLogAppName, subject, desc]);
end;
end; function TLogFile.WriteLogFile(const szFormat: string;
const Args: array of const): Boolean;
var
fileName: string;
currentTime: TDateTime;
currentTimeStamp: TTimeStamp;
currentSQLTimeStamp: TSQLTimeStamp;
buffer: string;
szDate, szTime: string;
begin
result := false; //进入临界区,保证多线程环境下此函数能安全执行
FCsWriteLogFile.Enter();
try
currentTime := Now(); //注意这里得到的是local time
currentSQLTimeStamp := DateTimeToSQLTimeStamp(currentTime);
currentTimeStamp := DateTimeToTimeStamp(currentTime); try
// . close the current log file?
if (FLogOpened and
(currentTimeStamp.Date <> FFileTimeStamp.Date)) then
begin
CloseFile(FLogFile);
FLogOpened := False;
end; // . whether to open a new log file?
if (not FLogOpened) then
begin
// 2.1如果指定的日志目录不存在,则创建它
if not DirectoryExists(FLogPath) then
if not ForceDirectories(FLogPath) then exit; // 2.2 然后再打开当前日志文件
szDate := Format('%4d%2d%2d',
[currentSQLTimeStamp.Year, currentSQLTimeStamp.Month, currentSQLTimeStamp.Day]);
// Format函数不支持在宽度不足位添0,只好用replace添加
szDate := StringReplace(szDate, ' ', '', [rfReplaceAll]); fileName := Format('%s%s%s.log', [FLogPath, FLogAppName, szDate]); Assignfile(FLogFile, fileName);
//if FileExists(fileName) then append(FLogFile)
//else rewrite(FLogFile); //$ modify by zhajl --
// 如果无法打开日志文件,则退出
try
if FileExists(fileName) then append(FLogFile)
else rewrite(FLogFile);
FLogOpened := True;
except
// 如果无法打开日志文件
FLogOpened := False;
//这里用CloseFile会出现异常
//CloseFile(FLogFile);
exit;
end; // 更新文件创建时间。要注意这里是 local time
FFileTimeStamp := DateTimeToTimeStamp(currentTime);
end; // . 写日志内容
ASSERT(FLogOpened);
if (FLogOpened) then
begin
szDate := Format('%4d/%2d/%2d',
[currentSQLTimeStamp.Year, currentSQLTimeStamp.Month, currentSQLTimeStamp.Day]);
// Format函数不支持在宽度不足位添0,只好用replace添加
szDate := StringReplace(szDate, ' ', '', [rfReplaceAll]);
szTime := Format('%2d:%2d:%2d',
[currentSQLTimeStamp.Hour, currentSQLTimeStamp.Minute, currentSQLTimeStamp.Second]);
szTime := StringReplace(szTime, ' ', '', [rfReplaceAll]); buffer := Format('%s %s ', [szDate, szTime]); // '%4d/%2d/%2d %2d:%2d:%2d '
buffer := buffer + szFormat;
buffer := Format(buffer, Args); writeln(FLogFile, buffer);
Flush(FLogFile); // 是否考虑性能而注释之?
end;
except
//写日志文件操作中若有异常(如目录是只读的等),则忽略它
end;
finally
FCsWriteLogFile.Leave; //离开临界区
end;
result := true;
end; end.

Delphi 写日志的类的更多相关文章

  1. C#写日志工具类

    代码: using System; using System.Collections.Generic; using System.IO; using System.Linq; using System ...

  2. 2.2 代码块--delphi 写日志模块

    //2.2 代码块--写日志 //调用例句如:LogMsg('FTP上传线程终止',False,true); procedure LogMsg(AMsg: string; const blnIsErr ...

  3. c# 多线程使用队列顺序写日志的类 (需要再优化)

    using System; using System.Collections.Generic; using System.Threading; public class LogManager { // ...

  4. PHP写日志公共类

    Txl_Log.php <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /** * * * ...

  5. 写日志(log)

    已下为我自己写的一个写日志的类,比较简洁. <?php class Log { /** * @Purpose : 写日志 * @Method Name : writeLog() * @param ...

  6. C#写文本日志帮助类(支持多线程)改进版(不适用于ASP.NET程序)

    由于iis的自动回收机制,不适用于ASP.NET程序 代码: using System; using System.Collections.Concurrent; using System.Confi ...

  7. C#写文本日志帮助类(支持多线程)

    代码: using System; using System.Configuration; using System.IO; using System.Threading.Tasks; namespa ...

  8. 重复造轮子,编写一个轻量级的异步写日志的实用工具类(LogAsyncWriter)

    一说到写日志,大家可能推荐一堆的开源日志框架,如:Log4Net.NLog,这些日志框架确实也不错,比较强大也比较灵活,但也正因为又强大又灵活,导致我们使用他们时需要引用一些DLL,同时还要学习各种用 ...

  9. .NET Core的日志[5]:利用TraceSource写日志

    从微软推出第一个版本的.NET Framework的时候,就在“System.Diagnostics”命名空间中提供了Debug和Trace两个类帮助我们完成针对调试和跟踪信息的日志记录.在.NET ...

随机推荐

  1. PHP Ctype函数(转)

    Ctype函数是PHP内置的字符串体测函数.主要有以下几种 ctype_alnum -- Check for alphanumeric character(s)检测是否是只包含[A-Za-z0-9] ...

  2. 零基础学习云计算及大数据DBA集群架构师【企业级运维技术及实践项目2015年1月29日周五】

    LNMP/LEMP项目搭建 { 项目框架 # Linux_____WEB_____PHP_____DB # rhel7_____apache__-(libphp5.so)-__php__-(php-m ...

  3. 什么是AAC音频格式 AAC-LC 和 AAC-HE的区别是什么

    Advanced Audio Coding(高级音频解码),是一种由MPEG-4标准定义的有损音频压缩格式,由Fraunhofer发展,Dolby, Sony和AT&T是主要的贡献者. 在使用 ...

  4. IP 转地址

    1.需要  QQWry.Dat IP 地址数据库 2辅助类库 using System; using System.Collections.Generic; using System.IO; usin ...

  5. editplus双击单词语法高亮显示设置

    view=>Word Highlighting

  6. (转)ecshop 后台商品分类添加图片的功能

    转之--http://blog.sina.com.cn/s/blog_4696b3760100n5ee.html   1 .首先找到数据表 ecs_category (商品分类表) 添加一 cat_i ...

  7. 三、改变struts.xml默认路径后web.xml如何配置

    http://yanln.iteye.com/blog/2189816(文章很好)

  8. iOS移动端架构的那些事!(转载)

    一个app的初始阶段,必然是先满足各种业务需求.然后,经过多次版本迭代之后,先前的由于急于满足需求而导致的杂乱代码则会充斥整个项目.而此时,项目有了一定的规模,有了一定数量的开发人员,那么为了达到快速 ...

  9. 【转】iOS开发系列--数据存取

    原文: http://www.cnblogs.com/kenshincui/p/4077833.html#SQLite 概览 在iOS开发中数据存储的方式可以归纳为两类:一类是存储为文件,另一类是存储 ...

  10. Swift - 31 - 常量参数, 变量参数和inout参数

    //: Playground - noun: a place where people can play import UIKit // swift中默认情况下, 传入的参数是不可以修改的, 也就是l ...