![]() |
Open Source "Logging Facade" für Pascal auf Github
Unter
![]() Wer schon mal schnuppern möchte, kann nun den Source Code und DUnit Tests von Github herunterladen. Für die Unit Tests wird das Log4D Open Source Framework benötigt, das auf Sourceforge gehostet wird. Da die Logging Facade auch in einem oder zwei meiner anderen Projekte eingesetzt werden soll, wird unter anderem auch Free Pascal Unterstützung und FPCUnit Tests folgen. Die Bibliothek steht unter der Apache 2.0 Lizenz. Über Vorschläge, welches (Open Source-) Logging Framework noch integriert werden sollte, freue ich mich natürlich. |
AW: Open Source "Logging Facade" für Pascal auf Github
Werde ich mir mal anschauen. Ich sehe zwar nicht, dass wir in absehbarer Zeit von Log4D weg wechseln, aber die Möglichkeit zu haben kann ja nie schaden. Wobei ich aktuell ehrlich gesagt, auch nicht wüsste, wohin wir wechseln sollten :-)
|
AW: Open Source "Logging Facade" für Pascal auf Github
Sieht interessant aus,
aber was ich mich bei dem Thema immer frage: Gibt es in Delphi eigentlich die Möglichkeit eine "leere" Prozedur zu definieren, als Beispiel mal das Object.Free
Delphi-Quellcode:
So das man beim Aufruf nicht immer hier reinspreingen muss, wenn nichts drin steht.
procedure TObject.Free;
begin // under ARC, this method isn't actually called since the compiler translates // the call to be a mere nil assignment to the instance variable, which then calls _InstClear {$IFNDEF AUTOREFCOUNT} if Self <> nil then Destroy; {$ENDIF} end; Also Obj.Free; wird doch immer aufgerufen, mit ein paar Zeilen Assembler für in- out-management. Aber schön wäre doch eine Debug Prozedur die gar nicht erst kompiliert wird, oder wenigstens ein nop, (natürlich ohne Fehlermeldungen), wenn das DEBUG Define nicht vorhanden ist. Ich denke da an soetwas wie die Defines/Macros von CPP, diese werden beim PreCompiler einfach ignotiert wenn nichts drinsteht. Also bei DEBUG Define: Log.Debug('Blah'); // wird aufgerufen und macht ihr Ding ohne DEBUG Define: Log.Debug('Blah'); // wird einfach ignoriert, und muss nicht erst rein- rausgesprungen werden Geht das, evtl. mit Interfaces ? Rollo |
AW: Open Source "Logging Facade" für Pascal auf Github
Du kannst so etwas mit
Delphi-Quellcode:
erreichen. Ohne das DEFINE Log sieht man schon keinen blauen Punkt for dem Log-Aufruf in Main.
inline
Delphi-Quellcode:
unit Unit58;
interface procedure Log(AText: string); inline; implementation {.$DEFINE Log} procedure Log(AText: string); begin {$IFDEF Log} Writeln(AText); {$ENDIF} end; end.
Delphi-Quellcode:
uses
Unit58 in 'Unit58.pas'; procedure Main; begin Log('Hallo Welt'); Writeln('Wie geht''s?'); Readln; end; |
AW: Open Source "Logging Facade" für Pascal auf Github
Zitat:
Einfach nen ![]() Die Performancebeeinflussung dafür ist imo nur theoretischer Natur. |
Zitat:
Delphi-Quellcode:
program Project201601291;
{$APPTYPE CONSOLE} type ITest = interface['{76BA1F8A-D171-4817-BB3D-337295B03CE0}'] procedure Log; end; TTest = class(TInterfacedObject, ITest) public procedure Log; inline; end; var T: ITest; procedure TTest.Log; begin end; begin T := TTest.Create; T.Log; end. |
AW: Open Source "Logging Facade" für Pascal auf Github
Zitat:
Log4D ist aktuell auch die einzige Bibliothek die ich rundum empfehlen kann (Log4Delphi hat beim ersten Versuch in eine Datei zu loggen bereits einen E/A Fehler 32 geworfen). p.s. zu Log4D: falls darin Bugs entdeckt und gefixt wurden, bin ich gerne bereit diese in meinem ![]() |
AW: Open Source "Logging Facade" für Pascal auf Github
Für mich persönlich gilt: SmartInspect or no logging ;) Ich kann diese ganzen Textfile basierten Logging Dinger nich ausstehen. Auch wenn sie html und schießmichtot Formatierung anbieten.
P.S. Scheint wir hatten in Spring4D vor einiger Zeit mal ![]() |
AW: Open Source "Logging Facade" für Pascal auf Github
Zitat:
|
AW: Open Source "Logging Facade" für Pascal auf Github
Als ich den Post gesehen habe, habe ich auch erst mal an
![]() ![]() |
AW: Open Source "Logging Facade" für Pascal auf Github
Zitat:
Delphi-Quellcode:
in der DPR nicht funktioniert, könnte man für das Logger-Interface auch einen Wrapper-Record definieren, der die Aufrufe unter IFDEF an das Interface weiterreicht. Damit wird keine der inlined Record-Methoden aufgerufen, wenn das entsprechende IFDEF nicht zutrifft. Einziger etwas unschöner Nebeneffekt ist, daß eine nicht verwendete Variable
inline
Delphi-Quellcode:
in Main angemeckert wird.
T
Delphi-Quellcode:
unit Unit58;
interface {.$DEFINE Log} type ILog = interface ['{76BA1F8A-D171-4817-BB3D-337295B03CE0}'] procedure Log(AText: string); end; TLog = record private {$IFDEF Log} FLog: ILog; {$ENDIF} public procedure Init(const AName: string); inline; procedure Log(AText: string); inline; end; implementation type TLogConsole = class(TInterfacedObject, ILog) public procedure Log(AText: string); end; procedure TLogConsole.Log(AText: string); begin Writeln(AText); end; procedure TLog.Init(const AName: string); begin {$IFDEF Log} // der Einfachheit halber FLog := TLogConsole.Create; {$ENDIF} end; procedure TLog.Log(AText: string); begin {$IFDEF Log} if FLog <> nil then begin FLog.Log(AText); end; {$ENDIF} end; end.
Delphi-Quellcode:
program Project67;
{$APPTYPE CONSOLE} {$R *.res} uses Unit58 in 'Unit58.pas'; procedure Main; var T: TLog; begin T.Init('TLogConsole'); T.Log('Hallo Welt'); Writeln('Wie geht''s?'); Readln; end; begin Main; end. |
AW: Open Source "Logging Facade" für Pascal auf Github
Zitat:
Michael |
AW: Open Source "Logging Facade" für Pascal auf Github
Wenn du einen Logger implementierst, dann musst du immer ganz schön viel Boilerplate-Code schreiben.
Da würde ich noch ein Interface mit Wrapper dazwischen schieben:
Delphi-Quellcode:
Mit einem Wrapper, kann man jetzt ganz kleine süße Log-Writer erstellen, die einfach nur
unit djLogWriter;
interface uses System.SysUtils, djLogAPI; type TLogLevel = ( llTrace, llDebug, llInfo, llWarn, llError ); TLogLevels = set of TLogLevel; type IWriteLog = interface procedure WriteMessage( const ALevel: TLogLevel; const AName, AMessage: string; const AException: Exception ); end; TLogWriterWrapper = class( TInterfacedObject, ILogger ) private { fields } FName : string; FWriter : IWriteLog; FLogFilter: TLogLevels; procedure SendToWriter( const ALevel: TLogLevel; const AMessage: string; const AException: Exception ); inline; private { ILogger } procedure Debug( const AMsg: string ); overload; procedure Debug( const AFormat: string; const AArgs: array of const ); overload; procedure Debug( const AMsg: string; const AException: Exception ); overload; procedure Error( const AMsg: string ); overload; procedure Error( const AFormat: string; const AArgs: array of const ); overload; procedure Error( const AMsg: string; const AException: Exception ); overload; procedure Info( const AMsg: string ); overload; procedure Info( const AFormat: string; const AArgs: array of const ); overload; procedure Info( const AMsg: string; const AException: Exception ); overload; procedure Warn( const AMsg: string ); overload; procedure Warn( const AFormat: string; const AArgs: array of const ); overload; procedure Warn( const AMsg: string; const AException: Exception ); overload; procedure Trace( const AMsg: string ); overload; procedure Trace( const AFormat: string; const AArgs: array of const ); overload; procedure Trace( const AMsg: string; const AException: Exception ); overload; function IsDebugEnabled: Boolean; function IsErrorEnabled: Boolean; function IsInfoEnabled: Boolean; function IsWarnEnabled: Boolean; function IsTraceEnabled: Boolean; function Name: string; public constructor Create( const AName: string; const AWriter: IWriteLog; const ALogFilter: TLogLevels ); end; implementation { TLogWriterWrapper } constructor TLogWriterWrapper.Create( const AName: string; const AWriter: IWriteLog; const ALogFilter: TLogLevels ); begin inherited Create; FName := AName; FWriter := AWriter; FLogFilter := ALogFilter; end; procedure TLogWriterWrapper.Debug( const AMsg: string ); begin SendToWriter( llDebug, AMsg, nil ); end; procedure TLogWriterWrapper.Debug( const AMsg: string; const AException: Exception ); begin SendToWriter( llDebug, AMsg, AException ); end; procedure TLogWriterWrapper.Debug( const AFormat: string; const AArgs: array of const ); begin SendToWriter( llDebug, Format( AFormat, AArgs ), nil ); end; procedure TLogWriterWrapper.Error( const AMsg: string ); begin SendToWriter( llError, AMsg, nil ); end; procedure TLogWriterWrapper.Error( const AFormat: string; const AArgs: array of const ); begin SendToWriter( llError, Format( AFormat, AArgs ), nil ); end; procedure TLogWriterWrapper.Error( const AMsg: string; const AException: Exception ); begin SendToWriter( llError, AMsg, AException ); end; procedure TLogWriterWrapper.Info( const AFormat: string; const AArgs: array of const ); begin SendToWriter( llInfo, Format( AFormat, AArgs ), nil ); end; procedure TLogWriterWrapper.Info( const AMsg: string ); begin SendToWriter( llInfo, AMsg, nil ); end; procedure TLogWriterWrapper.Info( const AMsg: string; const AException: Exception ); begin SendToWriter( llInfo, AMsg, AException ); end; function TLogWriterWrapper.IsDebugEnabled: Boolean; begin Result := not( llDebug in FLogFilter ); end; function TLogWriterWrapper.IsErrorEnabled: Boolean; begin Result := not( llError in FLogFilter ); end; function TLogWriterWrapper.IsInfoEnabled: Boolean; begin Result := not( llInfo in FLogFilter ); end; function TLogWriterWrapper.IsTraceEnabled: Boolean; begin Result := not( llTrace in FLogFilter ); end; function TLogWriterWrapper.IsWarnEnabled: Boolean; begin Result := not( llWarn in FLogFilter ); end; function TLogWriterWrapper.Name: string; begin Result := FName; end; procedure TLogWriterWrapper.SendToWriter( const ALevel: TLogLevel; const AMessage: string; const AException: Exception ); begin if not( ALevel in FLogFilter ) then FWriter.WriteMessage( ALevel, FName, AMessage, AException ); end; procedure TLogWriterWrapper.Trace( const AMsg: string ); begin SendToWriter( llTrace, AMsg, nil ); end; procedure TLogWriterWrapper.Trace( const AFormat: string; const AArgs: array of const ); begin SendToWriter( llTrace, Format( AFormat, AArgs ), nil ); end; procedure TLogWriterWrapper.Trace( const AMsg: string; const AException: Exception ); begin SendToWriter( llTrace, AMsg, AException ); end; procedure TLogWriterWrapper.Warn( const AMsg: string; const AException: Exception ); begin SendToWriter( llWarn, AMsg, AException ); end; procedure TLogWriterWrapper.Warn( const AMsg: string ); begin SendToWriter( llWarn, AMsg, nil ); end; procedure TLogWriterWrapper.Warn( const AFormat: string; const AArgs: array of const ); begin SendToWriter( llWarn, Format( AFormat, AArgs ), nil ); end; end.
Delphi-Quellcode:
implementieren.
IWriteLog
|
AW: Open Source "Logging Facade" für Pascal auf Github
Zitat:
Unter diesem Aspekt müsste ich auch, um den Quellcode nicht unnötig kompliziert zu machen, die Logger Factory und deren Registrierung nicht auf zwei Units aufteilen sondern in einer einzigen Datei zusammenfassen. Dann gibt es je unterstütztem Framework nur eine statt zwei Units. Aktuell sieht die Registrierungsunit z.B. für das Log4D Bindung so aus:
Delphi-Quellcode:
Diese Unit könnte problemlos mit dem Binding Code (Unit Log4DLogger) zusammengefasst werden.
unit djLogOverLog4D;
{$IFDEF FPC}{$MODE DELPHI}{$ENDIF} interface implementation uses djLoggerFactory, Log4DLogger; initialization RegisterFactory(TLog4DLoggerFactory.Create); end. |
AW: Open Source "Logging Facade" für Pascal auf Github
SLF4P Update:
das Lazarus LCL Logging über ![]() ![]() ![]() Das ![]() ![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:25 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz