#1 2014-10-17 16:59:44

AArhin
Member
Registered: 2013-12-30
Posts: 10

Logging

Hi,
   Is it possible to redirect server logging to a memo control on server main form ?

Offline

#2 2014-10-17 17:12:25

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,182
Website

Re: Logging

Yes, using the aLogClass.Family.EchoCustom property.

Offline

#3 2019-04-07 21:33:58

HollosCs
Member
Registered: 2015-12-08
Posts: 56

Re: Logging

Hi,
I have VCL form server application (not console)
When I set TSQLLog.EchoCustom my own log writer then application is freeze.

function TfrmRestServer.Echo(Sender:TTextWriter; Level:TSynLogInfo; const
    Text:RawUTF8): boolean;
begin
  Memo1.Lines.Add(Text); <- without this line, not freeze
  Result := true;
end;

How write log info to main form memo component?

Thanks, Csaba

Offline

#4 2019-04-08 06:33:39

pvn0
Member
From: Slovenia
Registered: 2018-02-12
Posts: 209

Re: Logging

TSQLLog.EchoCustom can be called from any number of threads, that memo1 line needs to be synchronized with the main thread.

Offline

#5 2019-04-08 06:48:12

HollosCs
Member
Registered: 2015-12-08
Posts: 56

Re: Logging

Yes, think this is the problem, but I dont find solution.

  TThread.Synchronize(nil,
    procedure
    begin
      Memo1.Lines.Add(Text);
    end
  );

Not working.

Offline

#6 2019-04-08 07:26:07

pvn0
Member
From: Slovenia
Registered: 2018-02-12
Posts: 209

Re: Logging

It works just fine, it's your code somewhere that is the issue, something you are not showing. Below is quick threaded example (XE7 required or higher).

unit Unit1;

interface

uses
  Winapi.Windows,
  Winapi.Messages,
  System.SysUtils,
  System.Variants,
  System.Classes,
  System.Threading,
  Vcl.Graphics,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.Dialogs,
  Vcl.StdCtrls,
  SynLog,
  SynCommons;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    function Echo(Sender: TTextWriter; Level: TSynLogInfo; const Text: RawUTF8): boolean;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
{ TForm1 }

function TForm1.Echo(Sender: TTextWriter; Level: TSynLogInfo; const Text: RawUTF8): boolean;
begin

  TThread.Synchronize(nil,
    procedure
    begin
      Memo1.Lines.Add(Text);
    end);

  Result := True;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  I: Integer;
  aTask: ITask;
begin

  with TSynLog.Family do
  begin
    Level := LOG_VERBOSE;
    NoFile := True;
    EchoCustom := Echo;
  end;

  for I := 0 to 1000 do
  begin
    aTask := TTask.Create(
      procedure()
      begin
        TSynLog.Add.Log(TSynLogInfo.sllInfo, 'TEST');
      end);
    aTask.Start;
  end;

end;

end.

Last edited by pvn0 (2019-04-08 07:29:13)

Offline

#7 2019-04-08 07:53:57

HollosCs
Member
Registered: 2015-12-08
Posts: 56

Re: Logging

This part is ok, but i log all event, like consol app.

    TSQLLog.Family.EchoToConsole := LOG_VERBOSE;
    HTTPServer := TSQLHttpServer.Create(HTTP_PORT,[ORMServer]);

I want in form app: start server and log into all to the memo.

Minimal code:

  TfrmRestServer = class(TForm)
    Memo1: TMemo;
  private
    { Private declarations }
    FRestServer:TSQLRestServerFullMemory;
    FhttpServer:TSQLHttpServer;
  public
    { Public declarations }
    function Echo(Sender:TTextWriter; Level:TSynLogInfo; const Text:RawUTF8):boolean;
  end;

function TfrmRestServer.Echo(Sender:TTextWriter; Level:TSynLogInfo; const Text:RawUTF8): boolean;
begin
  TThread.Synchronize(nil,
    procedure
    begin
      Memo1.Lines.Add(Text);
    end
  );
  Memo1.Lines.Add(Text);
  Result := true;
end;

...
  TSQLLog.Family.Level := LOG_VERBOSE;
  TSQLLog.Family.NoFile := True;
  TSQLLog.Family.EchoCustom := frmRestServer.Echo;


  FRestServer := TSQLRestServerTest.Create(TSQLModel.Create([]));
  FhttpServer := TSQLHttpServer.Create('888', [FRestServer]);

But not work, Write two line, after application is freeze.

Last edited by HollosCs (2019-04-08 08:50:24)

Offline

#8 2019-04-08 10:32:37

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,182
Website

Re: Logging

Please do not write so much code as part of the forum posts.
Please follow the rules - https://synopse.info/forum/misc.php?action=rules

Your code is wrong: it calls Memo1.Lines.Add(Text) twice - the 2nd call is executed in the current log thread, which is not correct.

Offline

#9 2019-04-08 10:47:01

HollosCs
Member
Registered: 2015-12-08
Posts: 56

Re: Logging

Sorry ab!
2nd line not in code, copy code accident, but not working without it also.
Which correct way to show log information in gui application?
Read periodically log file? The console echo is perfect, how can i this in forms?
Thanks, Csaba

Offline

#10 2019-04-08 11:58:25

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,182
Website

Re: Logging

Try to use a dedicated method, not an anonymous method.

Or try to use a timer for UI periodic refresh.

Offline

#11 2019-04-08 13:01:27

HollosCs
Member
Registered: 2015-12-08
Posts: 56

Re: Logging

Many thanks for everybody!
I got a solution, use TTask instead of CriticalSection or Syncronize.

Inside of EchoCustom function:

  aTask := TTask.Create(procedure begin  Memo1.Lines.Add(Text); end);
  aTask.Start;
  Result := true;

Offline

#12 2019-04-08 13:39:07

pvn0
Member
From: Slovenia
Registered: 2018-02-12
Posts: 209

Re: Logging

@HollosCs, I hope you don't run that code in production because it's an accident waiting to happen. If that solves your problem then you have bigger issues at hand.

My guess is you're running http and rest servers in main UI thread. You should not do that. You should create a worker thread for your server and then use a communication layer to communicate in between.

Offline

#13 2019-04-08 18:30:41

HollosCs
Member
Registered: 2015-12-08
Posts: 56

Re: Logging

@pvn0, Of course not. Demo project for 'real time' debug for server communication to and from variable clients.

Offline

Board footer

Powered by FluxBB