Skip to content

Commit

Permalink
Merge pull request #324 from synopse/feature/systemd_master
Browse files Browse the repository at this point in the history
Feature/systemd master
  • Loading branch information
synopse committed Jun 25, 2020
2 parents ccce198 + 325e10e commit 48a4bfc
Show file tree
Hide file tree
Showing 13 changed files with 460 additions and 55 deletions.
48 changes: 26 additions & 22 deletions SQLite3/Samples/11 - Exception logging/LogViewMain.lfm
Expand Up @@ -14,7 +14,7 @@ object MainLogView: TMainLogView
OnCreate = FormCreate
OnKeyDown = FormKeyDown
OnShow = FormShow
LCLVersion = '1.7'
LCLVersion = '2.0.7.0'
object Splitter2: TSplitter
Cursor = crVSplit
Left = 0
Expand Down Expand Up @@ -146,17 +146,17 @@ object MainLogView: TMainLogView
end
object lblServerRoot: TLabel
Left = 16
Height = 13
Height = 14
Top = 48
Width = 62
Width = 72
Caption = 'Server Root:'
ParentColor = False
end
object lblServerPort: TLabel
Left = 16
Height = 13
Height = 14
Top = 90
Width = 59
Width = 69
Caption = 'Server Port:'
ParentColor = False
end
Expand All @@ -182,10 +182,11 @@ object MainLogView: TMainLogView
PopupMenu = FilterMenu
Style = lbOwnerDrawFixed
TabOrder = 3
TopIndex = -1
end
object EditSearch: TEdit
Left = 16
Height = 21
Height = 31
Hint = 'Search (Ctrl+F, F3 for next) '
Top = 40
Width = 85
Expand Down Expand Up @@ -231,9 +232,9 @@ object MainLogView: TMainLogView
end
object MergedProfile: TCheckBox
Left = 22
Height = 19
Height = 23
Top = 283
Width = 112
Width = 137
Caption = 'Merge method calls'
OnClick = MergedProfileClick
TabOrder = 5
Expand Down Expand Up @@ -261,8 +262,8 @@ object MainLogView: TMainLogView
Top = 336
Width = 118
Caption = ' Threads '
ClientHeight = 78
ClientWidth = 114
ClientHeight = 81
ClientWidth = 116
TabOrder = 8
object BtnThreadNext: TButton
Left = 8
Expand Down Expand Up @@ -374,15 +375,15 @@ object MainLogView: TMainLogView
end
object edtServerRoot: TEdit
Left = 16
Height = 21
Height = 31
Top = 64
Width = 121
TabOrder = 11
Text = 'LogService'
end
object edtServerPort: TEdit
Left = 16
Height = 21
Height = 31
Top = 106
Width = 121
TabOrder = 12
Expand Down Expand Up @@ -415,7 +416,9 @@ object MainLogView: TMainLogView
Width = 121
ItemHeight = 0
OnDblClick = lstDaysDblClick
ScrollWidth = 119
TabOrder = 15
TopIndex = -1
end
end
object MemoBottom: TMemo
Expand Down Expand Up @@ -494,6 +497,7 @@ object MainLogView: TMainLogView
OnClickCheck = ThreadListBoxClickCheck
OnDblClick = ThreadListBoxDblClick
TabOrder = 0
TopIndex = -1
end
object pnlThreadBottom: TPanel
Left = 1
Expand Down Expand Up @@ -555,19 +559,19 @@ object MainLogView: TMainLogView
end
end
object FilterMenu: TPopupMenu
left = 88
top = 16
Left = 88
Top = 16
end
object OpenDialog: TOpenDialog
DefaultExt = '.log'
Filter = 'Log|*.log;*.txt;*.synlz'
Options = [ofHideReadOnly, ofPathMustExist, ofFileMustExist, ofEnableSizing]
left = 40
top = 80
Left = 40
Top = 80
end
object ListMenu: TPopupMenu
left = 40
top = 16
Left = 40
Top = 16
object ListMenuCopy: TMenuItem
Caption = '&Copy'
OnClick = ListMenuCopyClick
Expand All @@ -577,14 +581,14 @@ object MainLogView: TMainLogView
Enabled = False
Interval = 200
OnTimer = tmrRefreshTimer
left = 88
top = 80
Left = 88
Top = 80
end
object dlgSaveList: TSaveDialog
DefaultExt = '.log'
Filter = 'log|*.log|txt|*.txt|synlz|*.synlz'
Options = [ofOverwritePrompt, ofHideReadOnly, ofEnableSizing]
left = 136
top = 16
Left = 136
Top = 16
end
end
11 changes: 11 additions & 0 deletions SQLite3/Samples/11 - Exception logging/LogViewMain.pas
Expand Up @@ -34,7 +34,9 @@ interface
{$endif}
SynCommons,
SynLog,
{$ifdef WINDOWS}
SynMemoEx,
{$endif}
mORMotHttpServer;

type
Expand Down Expand Up @@ -96,6 +98,9 @@ TMainLogView = class(TForm)
btnThreadDown: TButton;
btnThreadUp: TButton;
lstDays: TListBox;
{$ifdef LINUX}
MemoBottom: TMemo;
{$endif}
procedure FormCreate(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure BtnFilterClick(Sender: TObject);
Expand Down Expand Up @@ -155,7 +160,9 @@ TMainLogView = class(TForm)
procedure ThreadListNameRefresh(Index: integer);
procedure ReceivedOne(const Text: RawUTF8);
public
{$ifdef WINDOWS}
MemoBottom: TMemoEx;
{$endif}
destructor Destroy; override;
property LogFileName: TFileName write SetLogFileName;
end;
Expand Down Expand Up @@ -332,6 +339,7 @@ procedure TMainLogView.FormCreate(Sender: TObject);
ProfileList.ColWidths[0] := 60;
ProfileList.ColWidths[1] := 1000;
ProfileList.Hide;
{$ifdef WINDOWS}
MemoBottom := TMemoEx.Create(self);
MemoBottom.Parent := PanelBottom;
MemoBottom.Align := alClient;
Expand All @@ -342,6 +350,7 @@ procedure TMainLogView.FormCreate(Sender: TObject);
MemoBottom.ReadOnly := true;
MemoBottom.ScrollBars := ssVertical;
MemoBottom.Text := '';
{$endif}
end;

procedure TMainLogView.FormShow(Sender: TObject);
Expand Down Expand Up @@ -1077,9 +1086,11 @@ procedure TMainLogView.PanelLeftResize(Sender: TObject);
procedure TMainLogView.PanelBottomResize(Sender: TObject);
var w: integer;
begin
{$ifdef WINDOWS}
w := MemoBottom.CellRect.Width;
if w > 0 then
MemoBottom.RightMargin := (PanelBottom.ClientWidth div w) - 7;
{$endif}
end;

end.
51 changes: 50 additions & 1 deletion SQLite3/Samples/36 - Simple REST Benchmark/README.md
Expand Up @@ -39,7 +39,7 @@ in RESTBEnchmark by passing `false` to then second parameter

### How to run

- compile program and run with `unix` parameter
- compile a program and run with `unix` parameter
```
./RESTBenchmark unix
```
Expand All @@ -62,3 +62,52 @@ sudo nginx -s reload
```
wrk http://localhost:8888/root/abc
```


## systemd integration

- socket activation
- journald logging (can be exported for LogView program)
- auto shutdown on inactivity

With combination of [Systemd Template Unit](https://fedoramagazine.org/systemd-template-unit-files/), `* A` DNS zone and
nginx virtual hosts we can build a "cloud solution" using mORMot services with per-customer process level isolation.

### Install Unit
Add our service to systemd (should be executed once).
This command activate `rest_benchmark` socket on port 8889
```bash
sudo ./installSystemSocket.sh
```

### Socket activation, auto shutdown and logs
Kill possible instances of RESTBenchmark program
```bash
killall -TERM RESTBenchmark
```

Now program is **NOT running**, lets send an HTTP request to a port configured in `rest_benchmark.socket` unit (8889)
```bash
curl http://localhost:8889/root/xyz
```
Magic - we got a response :) This is how systemd socket activation works.

Inside our demo program, in case it executed by systemd it:
- log all activity into journald (see EchoToConsoleUseJournal)
- stops after 10 seconds without GET requests (see inactivityWatchdog in RESTBenchmark.dpr)

Open new terminal window and run a command to watch logs from `rest_benchmark` services
```bash
journalctl -u rest_benchmark.service -f
```

Now wait for 10 second - service should shut down itself.

### journald and LogView (Samples/11 - Exception logging)

Logs from journald can be exported to format LogView understand. Example:
```bash
journalctl -u rest_benchmark.service --no-hostname -o short-iso-precise --since today | grep "RESTBenchmark\[.*\]: . " > todaysLog.log
```
better to grep by program PID `"RESTBenchmark\[12345]: . "` to include only one start/stop circle (on 2020-06 LogView do not allow to filter on PIDs)

62 changes: 56 additions & 6 deletions SQLite3/Samples/36 - Simple REST Benchmark/RESTBenchmark.dpr
Expand Up @@ -12,6 +12,8 @@ program RESTBenchmark;
{$APPTYPE CONSOLE}
{$endif}

{$I Synopse.inc} // LINUXNOTBSD

uses
{$I SynDprUses.inc} // use FastMM4 on older Delphi, or set FPC threads
SysUtils,
Expand All @@ -22,6 +24,13 @@ uses
mORMot, // RESTful server & ORM
mORMotSQLite3, // SQLite3 engine as ORM core
SynSQLite3Static, // staticaly linked SQLite3 engine
{$ifdef UNIX}
BaseUnix,
{$endif}
{$ifdef LINUXNOTBSD}
SynSystemd,
mORMotService,
{$endif}
mORMotHttpServer; // HTTP server for RESTful server

type
Expand Down Expand Up @@ -102,9 +111,14 @@ begin
ctxt.Returns(s);
end;

var
url: AnsiString;
keepAlive: boolean;
aRestServer: TSQLRestServer;
lastReadCount: TSynMonitorCount64;

procedure DoTest(const url: AnsiString; keepAlive: boolean);
var
aRestServer: TSQLRestServerDB;
aHttpServer: TSQLHttpServer;
aServices: TMyServices;
begin
Expand All @@ -126,33 +140,69 @@ begin
if (keepAlive) then
writeLn('is enabled') else
writeLn('is disabled');
{$ifdef LINUX}
SynDaemonIntercept(nil);
writeln('Press [Ctrl+C] or send SIGINT/SIGTERM to close the server.');
fpPause;
{$else}
write('Press [Enter] to close the server.');
readln;
{$endif}
finally
aHttpServer.Free;
end;
finally
aServices.Free;
end;
finally
aRestServer.Free;
FreeAndNil(aRestServer);
end;
end;

const
UNIX_SOCK_PATH = '/tmp/rest-bench.socket';

var
url: AnsiString;
keepAlive: boolean;

{$ifdef LINUX}
/// killa process after X second without GEt requests
function inactivityWatchdog(p: pointer): ptrint;
var currentRC: TSynMonitorCount64;
begin
repeat
sleep(10000); /// once per 10 second
if aRestServer = nil then // not initialized
continue;
currentRC := aRestServer.Stats.Read;
if (currentRC - lastReadCount) <= 0 then begin
SQLite3Log.Add.Log(sllServer, 'Terminating due to inactivity..');
FpKill(GetProcessID, SIGTERM);
break;
end;
lastReadCount := currentRC;
until false;
Result := 0;
end;
{$endif}
begin
// set logging abilities
SQLite3Log.Family.Level := LOG_VERBOSE;
//SQLite3Log.Family.EchoToConsole := LOG_VERBOSE;
SQLite3Log.Family.PerThreadLog := ptIdentifiedInOnFile;
SQLite3Log.Family.NoFile := true; // do not create log files for benchmark
{$ifdef UNIX}
{$ifdef LINUXNOTBSD}
if SynSystemd.ProcessIsStartedBySystemd then begin
SQLite3Log.Family.EchoToConsole := SQLite3Log.Family.Level;
SQLite3Log.Family.EchoToConsoleUseJournal := true;
if sd.listen_fds(0) = 1 then
url := '' // force to use socket passed by systemd
else
url := '8888';
// set a wachdog to kill our process after 10 sec of inactivity
// just for demo - in real life verifiing only read operations is not enought
lastReadCount := 0;
BeginThread(@inactivityWatchdog, nil);
end else
{$endif}
if (ParamCount>0) and (ParamStr(1)='unix') then begin
url := 'unix:' + UNIX_SOCK_PATH;
if FileExists(UNIX_SOCK_PATH) then
Expand Down
Expand Up @@ -39,6 +39,7 @@
</Target>
<SearchPaths>
<IncludeFiles Value="../..;../../..;$(ProjOutDir;$(ProjOutDir)"/>
<Libraries Value="../../../static/$(TargetCPU)-$(TargetOS)"/>
<OtherUnitFiles Value="../..;../../.."/>
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
Expand Down
@@ -0,0 +1,5 @@
ln -s "`pwd`/rest_benchmark.socket" /etc/systemd/system
ln -s "`pwd`/rest_benchmark.service" /etc/systemd/system
systemctl enable rest_benchmark.socket
systemctl start rest_benchmark.socket
systemctl status rest_benchmark.socket #output status to console

0 comments on commit 48a4bfc

Please sign in to comment.