YOUSEFUL / DELPHI / COMPONENTS

TAtlasFileSink

Writes UTF-8 lines to a file, with size rotation, daily files and retention.

Non-visual component Palette: Atlas Log Unit Atlas.LogSinks · Inherits TAtlasTextSink · Product Atlas Log

Description

Each event becomes one line in the sink's Layout and Pattern, UTF-8 without a byte order mark, ending in CR LF. The file is opened on the first event, appended to if it exists, and kept open with share-deny-write: other programs can read it while it is open (with fmOpenRead or fmShareDenyNone), but not write to it. Missing folders are created.

With FileName = 'logs\app.log':

A failed write closes the file and raises (the logger counts it); the next event opens it afresh. Not implemented: compression of archives and retention by total size or age. Behaviour on a full disk or with a file locked by another writer has not been tested.

Members

MemberKindWhat it does
DestroydestructorCloses the file and leaves the logger.
ClosemethodCloses the file now, for example so another program can move it; the next event reopens it and appends.
ActiveFileNamemethodThe file being written, built from FileName (relative if FileName is), or an empty string while the file is closed.
FileNamepropertyThe log file.
MaxBytespropertyThe size limit per file in bytes; 0 means no size rotation.
MaxFilespropertyHow many archives to keep besides the active file: rotated .1, .2 ...
DailypropertyOne file per day, named with the local date of each event (app.2026-09-21.log).
Createconstructor from TAtlasTextSinkCreates the sink with no file name, no limits, Layout = loText and the default pattern.
Layoutproperty from TAtlasTextSinkloText (default) writes each event with Pattern; loJson writes one JSON object per event (see TAtlasJsonFormatter).
Patternproperty from TAtlasTextSinkThe text pattern for loText, ignored for loJson.
Loggerproperty from TAtlasLogSinkThe logger this sink receives events from.
MinLevelproperty from TAtlasLogSinkThe sink's own threshold: events below it are ignored by this sink only.
Writemethod from TAtlasLogSinkWrites one event.
Flushmethod from TAtlasLogSinkPushes buffered output out, under the sink's lock.

Constructors

Create constructorinherited from TAtlasTextSink

constructor Create(AOwner: TComponent); override;

Creates the sink with no file name, no limits, Layout = loText and the default pattern.

Destructors

Destroy destructor

destructor Destroy; override;

Closes the file and leaves the logger.

Properties

FileName property

property FileName: string read FFileName write SetFileName;

The log file. A relative name is resolved against the current directory when the file is opened. Changing it closes the current file. Without a name, every write raises EAtlasLogError (The file sink has no FileName), which the logger counts in SinkErrors.

pascal
Files.FileName := TPath.Combine(TPath.GetDocumentsPath, 'MyApp\app.log');

MaxBytes property

property MaxBytes: Int64 read FMaxBytes write SetMaxBytes default 0;

The size limit per file in bytes; 0 means no size rotation. Negative values raise EAtlasLogError.

pascal
Files.MaxBytes := 10 * 1024 * 1024;

MaxFiles property

property MaxFiles: Integer read FMaxFiles write SetMaxFiles default 0;

How many archives to keep besides the active file: rotated .1, .2 ... files, or with Daily the older files matching the name. 0 keeps everything. Negative values raise EAtlasLogError.

pascal
Files.MaxFiles := 10;

Daily property

property Daily: Boolean read FDaily write SetDaily default False;

One file per day, named with the local date of each event (app.2026-09-21.log). The switch happens with the first event of a new day. Changing the property closes the current file.

pascal
Files.Daily := True;

Layout propertyinherited from TAtlasTextSink

property Layout: TAtlasLogLayout read FLayout write FLayout default loText;

loText (default) writes each event with Pattern; loJson writes one JSON object per event (see TAtlasJsonFormatter).

pascal
Sink.Layout := loJson;

Pattern propertyinherited from TAtlasTextSink

property Pattern: string read GetPattern write SetPattern stored IsPatternStored;

The text pattern for loText, ignored for loJson. Default {time:yyyy-mm-dd hh:nn:ss.zzz} [{level:short}] {category} {scope} {message}{exception}{props}; assigning an empty string restores it. Tokens are listed under TAtlasTextFormatter. An unknown token, an unterminated { or a single } raises EAtlasLogError and keeps the previous pattern. Line breaks in values are always escaped as \n in sinks. Set it before the sink starts receiving events.

pascal
Sink.Pattern := '{time:hh:nn:ss} {level:short} {category} {message}{exception}';

Logger propertyinherited from TAtlasLogSink

property Logger: TAtlasLogger read FLogger write SetLogger;

The logger this sink receives events from. Setting it registers the sink with that logger (and removes it from the previous one); nil detaches it. The same as calling TAtlasLogger.AddSink and RemoveSink. Either side may be destroyed first: the other is told and lets go.

pascal
Sink.Logger := Log;

MinLevel propertyinherited from TAtlasLogSink

property MinLevel: TAtlasLogLevel read FMinLevel write FMinLevel default llTrace;

The sink's own threshold: events below it are ignored by this sink only. It applies after the logger's threshold, so it can only narrow what the logger lets through. Default llTrace.

pascal
Files.MinLevel := llInfo;   // the file skips debug and trace

Methods

Close method

procedure Close;

Closes the file now, for example so another program can move it; the next event reopens it and appends.

ActiveFileName method

function ActiveFileName: string;

The file being written, built from FileName (relative if FileName is), or an empty string while the file is closed. With Daily it includes the date.

pascal
Writeln(Files.ActiveFileName);   // logs\app.2026-09-21.log

Write methodinherited from TAtlasLogSink

procedure Write(const Event: TAtlasLogEvent);

Writes one event. The logger calls it; you may call it too, for example to replay events from a TAtlasMemorySink into another sink. Events below MinLevel and events at llOff are ignored; otherwise DoWrite runs under the sink's lock. Unlike the logger, Write itself may raise when the output fails.

Flush methodinherited from TAtlasLogSink

procedure Flush;

Pushes buffered output out, under the sink's lock. TAtlasLogger.Flush calls it on every sink and counts failures; called directly it may raise. For a file sink it asks Windows to write the file's buffers to disk (FlushFileBuffers).

Examples

Size rotation with ten archives

At most eleven files of 10 MB each: app.log and app.1.log to app.10.log.

pascal
uses System.SysUtils, System.IOUtils, Atlas.Log, Atlas.LogSinks;

function AddRotatingFile(Log: TAtlasLogger): TAtlasFileSink;
begin
  Result := TAtlasFileSink.Create(Log);
  Result.FileName := TPath.Combine(TPath.GetHomePath, 'MyApp\logs\app.log');
  Result.MaxBytes := 10 * 1024 * 1024;
  Result.MaxFiles := 10;
  Result.MinLevel := llInfo;
  Result.Logger := Log;
end;

Daily JSON files

One JSON-lines file per day, keeping fourteen older days.

pascal
uses Atlas.Log, Atlas.LogSinks;

function AddDailyJson(Log: TAtlasLogger): TAtlasFileSink;
begin
  Result := TAtlasFileSink.Create(Log);
  Result.FileName := 'C:\ProgramData\MyApp\logs\events.jsonl';
  Result.Daily := True;     // events.2026-09-21.jsonl
  Result.MaxFiles := 14;
  Result.Layout := loJson;
  Result.Logger := Log;
end;

Read the file while it is open

The sink denies other writers, so readers must allow writing.

pascal
uses System.SysUtils, System.Classes, Atlas.LogSinks;

function ReadActiveLog(Files: TAtlasFileSink): string;
var
  Stream: TFileStream;
  Bytes: TBytes;
begin
  Result := '';
  if Files.ActiveFileName = '' then Exit;   // closed: nothing written since
  Stream := TFileStream.Create(Files.ActiveFileName, fmOpenRead or fmShareDenyNone);
  try
    SetLength(Bytes, Stream.Size);
    if Length(Bytes) > 0 then Stream.ReadBuffer(Bytes[0], Length(Bytes));
  finally
    Stream.Free;
  end;
  Result := TEncoding.UTF8.GetString(Bytes);
end;

TAtlasTextSink · TAtlasAsyncSink · TAtlasLogLayout · TAtlasTextFormatter · TAtlasJsonFormatter

Also in Atlas Log

TAtlasLogger · TAtlasMemorySink · TAtlasCallbackSink · TAtlasConsoleSink · TAtlasDebugSink · TAtlasAsyncSink · TAtlasLogView