TLogger一个D7可用的轻量级日志

♀尐吖头ヾ 提交于 2019-12-29 05:24:18

今天调程序,要用到日志。XE7有Qlog,D7用什么

从网上找到了Logger,下载的原文是不支持D7的,不过也只是很少的地方不同,自己修改了下就可以用了

感谢原作者和红鱼的分享

unit Logger;
// =======================================================================
// 鏃ュ織绫伙紙TLogger锛?ver.1.0
// 绾㈤奔鍎?http://blog.sina.com.cn/hblyuhong
// 2014/06/24
// 鍩轰簬1.0淇敼
// PFeng  (http://www.pfeng.org / xxmc01#gmail.com)
// 2012/11/08
// 鏃ュ織绾у埆绾﹀畾锛?
// 0 - Information
// 1 - Notice
// 2 - Warning
// 3 - Error
// =======================================================================

interface

uses Windows, Classes, SysUtils, StdCtrls, ComCtrls, ComObj, Messages;

const
  WRITE_LOG_DIR = 'log\'; // 璁板綍鏃ュ織榛樿鐩綍
  WRITE_LOG_MIN_LEVEL = 0; // 璁板綍鏃ュ織鐨勬渶浣庣骇鍒紝灏忎簬姝ょ骇鍒彧鏄剧ず涓嶈褰?
  WRITE_LOG_ADD_TIME = True; // 璁板綍鏃ュ織鏄惁娣诲姞鏃堕棿
  WRITE_LOG_TIME_FORMAT = 'hh:nn:ss.zzz'; // 璁板綍鏃ュ織娣诲姞鏃堕棿鐨勬牸寮?
  SHOW_LOG_ADD_TIME = True; // 鏃ュ織鏄剧ず瀹瑰櫒鏄惁娣诲姞鏃堕棿
  SHOW_LOG_TIME_FORMAT = 'yyyy/mm/dd hh:nn:ss.zzz'; // 鏃ュ織鏄剧ず娣诲姞鏃堕棿鐨勬牸寮?
  SHOW_LOG_CLEAR_COUNT = 1000; // 鏃ュ織鏄剧ず瀹瑰櫒鏈€澶ф樉绀烘潯鏁?

type
  TLogger = class
  private
    FCSLock: TRTLCriticalSection; // 涓寸晫鍖?
    FFileStream: TFileStream; // 鏂囦欢娴?
    FLogShower: TComponent; // 鏃ュ織鏄剧ず瀹瑰櫒
    FLogName: String; // 鏃ュ織鍚嶇О
    FEnabled: Boolean;
    FLogFileDir: string; // 鏃ュ織鐩綍
    procedure SetEnabled(const Value: Boolean);
    procedure SetLogFileDir(const Value: string);
    procedure SetLogShower(const Value: TComponent);
  protected
    procedure ShowLog(Log: String; const LogLevel: Integer = 0);
  public
    procedure WriteLog(Log: String; const LogLevel: Integer = 0); overload;
    procedure WriteLog(Log: String; const Args: array of const; const LogLevel: Integer = 0); overload;

    constructor Create;
    destructor Destroy; override;

    // 启用
    property Enabled: Boolean read FEnabled write SetEnabled;
    // 日志目录
    property LogFileDir: string read FLogFileDir write SetLogFileDir;
    // 显示控件
    property LogShower: TComponent read FLogShower write SetLogShower;

  end;

implementation

constructor TLogger.Create;
begin
  InitializeCriticalSection(FCSLock);
  FLogShower := nil;
  LogFileDir := ExtractFilePath(ParamStr(0)) + WRITE_LOG_DIR;
end;

procedure TLogger.WriteLog(Log: String; const Args: array of const; const LogLevel: Integer = 0);
begin
  WriteLog(Format(Log, Args), LogLevel);
end;

procedure TLogger.WriteLog(Log: String; const LogLevel: Integer = 0);
var
  logName: String;
  fMode: Word;
  Fstrs:TStringStream;
begin
  EnterCriticalSection(FCSLock);
  try
    if not Enabled then
      Exit;

    ShowLog(Log, LogLevel); // 鏄剧ず鏃ュ織鍒板鍣?
    if LogLevel >= WRITE_LOG_MIN_LEVEL then
    begin
      logName := FormatDateTime('yyyymmdd', Now) + '.log';
      if FLogName <> logName then
      begin
        FLogName := logName;
        if FileExists(FLogFileDir + FLogName) then // 濡傛灉褰撳ぉ鐨勬棩蹇楁枃浠跺瓨鍦?
          fMode := fmOpenWrite or fmShareDenyNone
        else
          fMode := fmCreate or fmShareDenyNone;

        if Assigned(FFileStream) then
          FreeAndNil(FFileStream);
        FFileStream := TFileStream.Create(FLogFileDir + FLogName, fMode);
      end;

      FFileStream.Position := FFileStream.Size; // 杩藉姞鍒版渶鍚?
      case LogLevel of
        0:
          Log := '[Information] ' + Log;
        1:
          Log := '[Notice] ' + Log;
        2:
          Log := '[Warning] ' + Log;
        3:
          Log := '[Error] ' + Log;
      end;
      if WRITE_LOG_ADD_TIME then
        Log := FormatDateTime(WRITE_LOG_TIME_FORMAT, Now) + ' ' + Log + #13#10;


      Fstrs:=TStringStream.Create(log);
      Fstrs.Position:=0;
      FFileStream.CopyFrom(Fstrs,Fstrs.Size);
    end;
  finally
    FreeAndNil(Fstrs);
    LeaveCriticalSection(FCSLock);
  end;
end;

procedure TLogger.SetEnabled(const Value: Boolean);
begin
  FEnabled := Value;
end;

procedure TLogger.SetLogFileDir(const Value: string);
begin
  FLogFileDir := Value;
  if not DirectoryExists(FLogFileDir) then
    if not ForceDirectories(FLogFileDir) then
    begin
      raise Exception.Create('日志路径错误,日志类对象不能被创建');
    end;
end;

procedure TLogger.SetLogShower(const Value: TComponent);
begin
  FLogShower := Value;
end;

procedure TLogger.ShowLog(Log: String; const LogLevel: Integer = 0);
var
  lineCount: Integer;
  listItem: TListItem;
begin
  if FLogShower = nil then
    Exit;
  if (FLogShower is TMemo) then
  begin
    if SHOW_LOG_ADD_TIME then
      Log := FormatDateTime(SHOW_LOG_TIME_FORMAT, Now) + ' ' + Log;
    lineCount := TMemo(FLogShower).Lines.Add(Log);
    // 滚动到最后一个
    SendMessage(TMemo(FLogShower).Handle, WM_VSCROLL, SB_LINEDOWN, 0);
    if lineCount >= SHOW_LOG_CLEAR_COUNT then
      TMemo(FLogShower).Clear;
  end
  else if (FLogShower is TListBox) then
  begin
    if SHOW_LOG_ADD_TIME then
      Log := FormatDateTime(SHOW_LOG_TIME_FORMAT, Now) + ' ' + Log;
    lineCount := TListBox(FLogShower).Items.Add(Log);
    SendMessage(TListBox(FLogShower).Handle, WM_VSCROLL, SB_LINEDOWN, 0);
    if lineCount >= SHOW_LOG_CLEAR_COUNT then
      TListBox(FLogShower).Clear;
  end
  else if (FLogShower is TListView) then
  begin
    listItem := TListView(FLogShower).Items.Add;
    if SHOW_LOG_ADD_TIME then
      listItem.Caption := FormatDateTime(SHOW_LOG_TIME_FORMAT, Now);
    if Assigned(TListView(FLogShower).SmallImages) and (TListView(FLogShower).SmallImages.Count - 1 >= LogLevel) then
      listItem.ImageIndex := LogLevel; // 根据不同等级显示不同图片
    listItem.SubItems.Add(Log);
    SendMessage(TListView(FLogShower).Handle, WM_VSCROLL, SB_LINEDOWN, 0);
    if TListView(FLogShower).Items.Count >= SHOW_LOG_CLEAR_COUNT then
      TListView(FLogShower).Items.Clear;
  end
  else
    raise Exception.Create('日志容器类型不支持' + FLogShower.ClassName);
end;

destructor TLogger.Destroy;
begin
  DeleteCriticalSection(FCSLock);
  if Assigned(FFileStream) then
    FreeAndNil(FFileStream);
end;

end.

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!