# Live log viewer A VCL program with a `TAtlasLogView` showing a `TAtlasMemorySink` while the application logs, from the main thread and from worker threads. The form is built in code; there is no `.dfm`. ## What it demonstrates - A `TAtlasLogger` and a `TAtlasMemorySink` (`Capacity` 2000) owned by the form. - A `TAtlasLogView` with `Sink`, `RefreshInterval := 100` and a monospaced font. It polls the sink's `Version` on a main-thread timer, so events logged on other threads never touch the control directly. - Level colours: trace and debug grey, warnings amber, errors red, fatal dark red and bold. - **Log a batch**: a channel, a scope nested inside a timed scope (`[batch/checkout]`), template properties, and the timer's `batch finished in N ms` line. - **Log a failure**: an exception logged with `Failure`. - **Four threads**: 4 x 501 events. With the capacity at 2000, older events are pushed out of the ring buffer; the status line shows `Discarded`. - The level box sets `MinLevel` and the text box sets `FilterText` (matched against the formatted row, ignoring case). - **Copy** calls `CopyToClipboard` (selected rows, or every shown row when nothing is selected); **Clear** empties the sink and the view follows. - The form waits for its worker threads before it frees the logger. ## Build and run Open `LiveLogViewer.dpr` in Delphi 13; the IDE creates the project file. Add the Atlas Log `src` folder and the `shared` folder to the project's search path, then build and run for Win32 or Win64. No packages need to be installed. The `shared` folder is part of the sample download. It holds `Atlas.TestVcl.pas`, which the optional snapshot mode uses to save a picture of the window. Run it without arguments to use the window. Run it with a file name to log one batch, save a PNG of the window and exit: ``` LiveLogViewer.exe window.png ``` ## Expected result A 1000 x 560 window with a button bar, a level box, a filter box, the log view and a status line. After **Log a batch** the view shows seven rows like these (times differ): ``` 21:37:53.127 INF [batch] Batch started 21:37:53.127 TRC [batch] Reading 3 rows {count=3} 21:37:53.127 INF orders [batch/checkout] Order 1042 placed by Contoso for 1250.5 {id=1042, customer=Contoso, total=1250.5} 21:37:53.127 WRN orders [batch/checkout] Stock for AX-7 is low: 3 left {sku=AX-7, left=3} 21:37:53.127 ERR orders [batch/checkout] Payment 77 was declined {id=77} 21:37:53.127 FTL [batch] Batch aborted 21:37:53.127 DBG [batch] batch finished in 0 ms {scope=batch, elapsed_ms=0} ``` The status line reads `7 of 7 events shown, 0 pushed out of the ring buffer`. The view keeps the newest row in sight unless you select a row further up. ## Adapting it Put the logger and memory sink wherever your application creates its logging (a data module, or the shared `AtlasLog`), and drop a `TAtlasLogView` on a diagnostics form with `Sink` pointing at the memory sink. Change the row format with `Pattern`, for example `'{time:hh:nn:ss} {level:short} {category} {message}'`. Give the memory sink a capacity that matches how far back people need to look; the view's cost does not grow with it, because only visible rows are drawn.