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. 基于SSH的数据库中图片的读写

    近期项目中遇到了这个问题,网上查了一些资料所谓是零零散散,这里写篇博文做个笔记. 注:这篇博文中部分类的属性声明未列出,应该不算难,基本都是以private 类型 名称 格式声明,然后配getter ...

  2. GridView禁止上下滚动的方法

    通常情况下,我们使用GridView来完成类似表格的布局,这种布局,我们只需要设置列数,会自动根据适配器的数据进行适配,非常灵活. GridView其实就是一个容器.允许向其内部添加控件,通常情况下, ...

  3. android 安全退出应用程序的几种方法

    android 安全退出应用程序的几种方法 正常关闭应用程序: 当应用不再使用时,通常需要关闭应用,可以使用以下三种方法关闭android应用: 第一种方法:首先获取当前进程的id,然后杀死该进程.a ...

  4. 【开源java游戏框架libgdx专题】-08-中文显示与绘制

    libgdx虽然是由美国人Mario Zechner(即BadlogicGames)写的开源引擎,由于Libgdx底层是用OpenGL实现的,所以Libgdx是可以支持中文的,在libgdx中的汉字都 ...

  5. C#—委托分析

    1.简单委托示例 using System; using System.Collections.Generic; using System.Linq; using System.Text; names ...

  6. OD: Kernel Vulnerabilities

    内核漏洞概述 内核漏洞的分类 运行在 Ring0 上的操作系统内核.设备驱动.第三方驱动能共享同一个虚拟地址空间,可以完全访问系统空间的所有内存,而不像用户态进程那样拥有独立私有的内存空间.由于内核程 ...

  7. 基于Bootstrap实现下图所示效果的页面,一个白底的带有两个菜单项、一个下拉菜单和一个登录表单的基本导航条

    <!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="utf-8& ...

  8. jquery获取元素到页面顶部距离

    jquery获取元素到页面顶部距离的语句为: $(selector).offset().top

  9. 安卓应用开发用户体验之禁止EditText自动获取焦点

    一.问题描述: 在安卓应用开发时,经常会在同一个页面有许多不同的控件,在用户操作时,如何正确的在这些控件之间来回切换是良好用户体验的重要问题.可能会碰到如下问题:在点击页面内某控件时(假设控件为Spi ...

  10. backbone学习笔记(一)

    因为工作的需要,从今天起对backbone的学习过程做下记录. 学习计划: 1.1周看基本知识(2014/1/18-2014/1/25) 2.基本知识总结(2014/1/26) 3.半周按教程写hel ...