LMD LogTools tutorial
Contents
Delphi LMDLog package
Basic using
Main purpose of this tool package is logging and monitoring actions of application. It should be used when you can't run regular debugger or when it useless - multi-thread application, system services, applications on client site etc.
Сurrent pre-beta version provides basic features only. To start use LogTools in your application you should add LMDLogMessage.pas unit to uses section of your unit, then you'll be able to use LMDLog instance of TLMDLogSession class.
<delphi> uses
..., LMDLogMessage, ...;
...
LMDLog.SendString('Test', 'Hello, World!');
... </delphi>
TLMDLogSession class has methods to send some info into main log - TLMDLogSession.Send*, to watch data in Watch area - TLMDLogSession.Watch* (main different with Send* function that Watch* has just changed value of watched variables, but not add new record)
<delphi> uses
..., LMDLogMessage, ...;
...
while i < 200 do
LMDLog.WatchInteger('i', i);
... </delphi>
To logging flow of application, below methods available: TLMDLogSession.Enter*, TLMDLogSession.Leave*. Sample:
<delphi> uses
..., LMDLogMessage, ...;
... function TestFunction: HResult; begin
LMDLog.EnterMethod('TestFunction');
try
...
finally
LMDLog.SendHResult('Result', Result);
LMDLog.LeaveMethod('TestFunction');
end;
end; ... </delphi>
and methods that help to trace of application
<delphi> uses
..., LMDLogMessage, ...;
...
for i := 0 to Count - 1 do
begin
LMDLog.SendInteger('Iteration', i);
b := 20 + i;
LMDLog.TouchCounter('Checkpoint');
a := CalcA(b);
LMDLog.TouchCounter('Checkpoint');
c := a div 34;
LMDLog.ReleaseCounter('Checkpoint');
end;
... </delphi>
To control log storage TLMDLogSession has next methods - TLMDLogSession.ClearLog, TLMDLogSession.ClearWatch and TLMDLogSession.ClearCallStack
TLMDLogSession allow you to control level of you logging messages. It has two properties for it - TLMDLogSession.AllowLogLevel - set minimum log level for messages, TLMDLogSession.DefaultLogLevel - set default log level for messages where level is not set as parameter.
<delphi> uses
..., LMDLogMessage, ...;
...
{$ifdef DEBUG}
LMDLog.AllowLogLevel := LogAll;
LMDLog.AllowLogLevel := LogAll;
{$ELSE}
LMDLog.AllowLogLevel := LogFatal;
LMDLog.DefaultLogLevel := LogOff;
{$ENDIF}
for i := 0 to 4 do
begin
try
LMDLog.SendInteger('i', i);
a := 5 / i;
LMDLog.SendReal('a', a);
except
on E: EDivideByZero do
LMDLog.SendString(LogFatal, 'Error', 'Divide by zero');
end;
end;
... </delphi> Logging for 'a' and 'i' will be turned off when DEBUG undefined, but 'Error' will be sent to log in any case.
AnyLogger console application
This logging and monitoring console for LMD Log package. All data that you send from your application are collected and displayed here.
Creating Viewer plugin for AnyLogger console
NB. This API information can be changed before AnyLogger release
AnyLogger console can be extended by pluggable modules (plugins). Plugins based on new package [LMD Plugins]. Currently you can create plugin to view custom data, that you sent to console, in more obvious form.
To create such plugin you will need LMD Plugins package and uCreatePlugin.pas unit.
<delphi> unit uCreatePlugin;
interface
uses
SysUtils, Forms, LMDPluginManager, LMDPluginImpl;
type
TLMDActionExecutor = class(TObject) public procedure GetCount(const AnAction: ILMDAction; var AResult: ILMDParameter); virtual; stdcall; abstract; procedure GetType(const AnAction: ILMDAction; var AResult: ILMDParameter); virtual; stdcall; abstract; procedure GetIcon(const AnAction: ILMDAction; var AResult: ILMDParameter); virtual; stdcall; abstract; procedure GetName(const AnAction: ILMDAction; var AResult: ILMDParameter); virtual; stdcall; abstract; end;
function CreatePlugin(AExecuter: TLMDActionExecutor; AFormClass: TFormClass): ILMDPlugin;
implementation
function CreatePlugin(AExecuter: TLMDActionExecutor; AFormClass: TFormClass): ILMDPlugin; var
Plugin: TLMDPlugin;
begin
try
// Create the plugin
Plugin := TLMDPlugin.Create('Author', 'AnyLogger plugin', 0, 1);
// add GetSupportedSubTypesCount action
Plugin.AddAction('GetSubTypesCount').OnPerformAction := AExecuter.GetCount;
with Plugin.AddAction('GetSubTypeName') do
begin
with AddParameter('SubType') do
ParameterType := ptGUID;
OnPerformAction := AExecuter.GetName;
end;
with Plugin.AddAction('GetSubType') do
begin
with AddParameter('Index') do
ParameterType := ptInteger;
OnPerformAction := AExecuter.GetType;
end;
with Plugin.AddAction('GetSubTypeIconIndex') do
begin
with AddParameter('SubType') do
ParameterType := ptGUID;
OnPerformAction := AExecuter.GetIcon;
end;
// add form into plugin
Plugin.AddForm(TLMDDelphiPluginForm.Create('Viewer', AFormClass));
// return the plugin Result := Plugin; except Result := nil; exit; end;
end;
end. </delphi>
uCreatePlugin.pas create TLMDPlugin instance and init with three plugin method "GetSubTypesCount" - returns count of lmdlog message subtypes that will showed by this plugins. Next method is "GetSubTypeName" - returns name of subtype by it's index (0..GetSubTypesCount - 1). "GetSubType" method returns GUID that identificate subtype. And the last method is "GetSubTypeIconIndex" - it returns iconindex to show icon in AnyLogger console by subtype GUID.
So, uCreatePlugin.pas do above basic steps for you. Next, you need to create form with interface ILMDFormWithData, which described in LMDPluginManager unit from [LMD Plugins] package.
