Become a member!

Konsolenfarben im Colorama-Stil (Python) und Gin-Style Logs (Go) in DMVCFramework

🌐
Dieser Artikel ist auch in anderen Sprachen verfügbar:
🇮🇹 Italiano  •  🇬🇧 English  •  🇪🇸 Español

Die Rueckkehr der Konsole

Konsolenanwendungen erleben eine zweite Bluetezeit. Das ist keine Nostalgie: Es ist ein konkreter Trend, angetrieben von einigen der relevantesten technologischen Entwicklungen der letzten Jahre.

KI-Agenten leben in der Konsole. Claude Code, GitHub Copilot CLI, Aider, Cursor Agent - die KI-gestuetzten Entwicklungstools sind Kommandozeilenanwendungen. Sie haben keine GUI: Sie lesen und schreiben Code und kommunizieren mit dem Entwickler ueber das Terminal. Und sie tun dies mit reichhaltiger, farbiger und strukturierter Ausgabe, denn wenn die Interaktion textbasiert ist, zaehlt jedes visuelle Detail.

MCP-Server (Model Context Protocol) sind Konsolenprozesse. Das MCP-Protokoll von Anthropic, das sich zum Standard fuer die Verbindung von KI-Agenten mit externen Tools entwickelt, basiert auf Servern, die ueber stdin/stdout kommunizieren. Jeder MCP-Server ist eine Konsolenanwendung. Und mit Delphi kann man native, schnelle MCP-Server als einzelne ausfuehrbare Datei schreiben - ein enormer Vorteil gegenueber den Pendants in Python oder TypeScript, die Runtime-Umgebungen und Abhaengigkeiten erfordern.

Microservices sind (oft) Konsolenanwendungen. Docker-Container, systemd-Services, Windows-Dienste: Das vorherrschende Muster im modernen Backend ist eine ausfuehrbare Datei ohne GUI, die auf die Konsole loggt. Moderne Web-Frameworks - von Go mit Gin bis Python mit FastAPI und uvicorn - haben alle in farbige und strukturierte Konsolenlogs investiert, weil der Entwickler dort waehrend der Entwicklung seine Zeit verbringt.

CLI-Tools sind ueberall. gh, docker, kubectl, terraform, npm - die Werkzeuge, die wir taeglich nutzen, sind Konsolenanwendungen mit gepflegter Ausgabe. Ein Kommandozeilentool mit monochromer und unstrukturierter Ausgabe wirkt sofort veraltet.

In diesem Kontext ist eine erstklassige Unterstuetzung fuer farbige Konsolenausgabe kein Luxus: Es ist eine Notwendigkeit. Deshalb habe ich in DelphiMVCFramework ein zweistufiges ANSI-Farbsystem eingefuehrt:

  1. Colorama-Style Primitive (Fore, Back, Style) - komponierbare String-Konstanten zum Einfaerben beliebiger Konsolenausgaben, inspiriert von colorama fuer Python
  2. Gin-Style Renderer - strukturierte und farbige HTTP-Logs, inspiriert vom Logger von Gin fuer Go, automatisch aktiviert in jeder DMVC-Anwendung

Die Konsolenfarben sind nur eine der vielen Neuheiten, die mit DMVCFramework 3.5.0 “Silicon” kommen:

  • Asymmetrisches JWT (RS256, PS256, ES256, EdDSA)
  • JWKS-Verifizierung und OIDC-Integration
  • SSE- und JSONL-Streaming
  • RangeMedia-Middleware (RFC 7233)
  • Oracle 12c+ Unterstuetzung in ActiveRecord
  • Komplett ueberarbeiteter IDE-Wizard
  • Konsolen-Spinner und ANSI-Farben
  • …und vieles mehr

Ich werde alles vorab auf der ITDevCon 2026 Spring Edition praesentieren. Wie alle Fruehjahrsausgaben findet die Konferenz ausschliesslich auf Italienisch statt - eine perfekte Gelegenheit, jedes Detail mit der Community zu vertiefen. Wer die internationale Ausgabe auf Englisch bevorzugt, ist im November zur zweitaegigen Konferenz eingeladen. Jetzt anmelden!

Die Colorama-Style API: Fore, Back, Style

Die Unit MVCFramework.Console.pas ist Teil des DMVCFramework-Repositories, hat aber keinerlei Abhaengigkeit vom Framework. Sie koennen sie kopieren und in jedem beliebigen Delphi-Konsolenprojekt verwenden - einem Server, einem Kommandozeilentool, einem MCP-Server - ohne weitere Abhaengigkeiten von DMVCFramework einbinden zu muessen.

“Einfachheit ist die höchste Form der Raffinesse” - dieses Zitat, das Leonardo da Vinci zugeschrieben wird, ist das Prinzip, das das Design dieser API geleitet hat. Keine Klassen, keine Objekte, keine Methoden, keine Interfaces. Nur drei Records mit String-Konstanten: Fore (Textfarbe), Back (Hintergrundfarbe) und Style (Stil). Jede Konstante ist eine ANSI-Escape-Sequenz, die sich durch einfache Verkettung zusammenfuegen laesst - genau wie colorama in Python.

Man haette ein Builder-Pattern mit Method-Chaining erstellen koennen, ein Theme-System mit Vererbung, einen thread-sicheren Color-Manager mit Dependency Injection. Aber wozu?

“Komplexität sollte mit dem Skalpell hinzugefügt werden, nicht mit der Schaufel.” — Daniele Teti

Dies ist ein Prinzip, das ich oft in meinen Kursen wiederhole und das jede Design-Entscheidung in DMVCFramework leitet. Wenn das Problem einfach ist - Text in der Konsole einfaerben - muss die Loesung ebenso einfach sein. Wenn man eine ganze Klassenhierarchie braucht, um eine gruene Zeile zu schreiben, ist etwas schiefgelaufen.

Grundfarben

program ColorBasics;
{$APPTYPE CONSOLE}
uses
  System.SysUtils, MVCFramework.Console;

begin
  EnableANSIColorConsole;

  WriteLn(Fore.Red     + 'This is red text'     + Style.ResetAll);
  WriteLn(Fore.Green   + 'This is green text'   + Style.ResetAll);
  WriteLn(Fore.Yellow  + 'This is yellow text'  + Style.ResetAll);
  WriteLn(Fore.Blue    + 'This is blue text'    + Style.ResetAll);
  WriteLn(Fore.Cyan    + 'This is cyan text'    + Style.ResetAll);
  WriteLn(Fore.Magenta + 'This is magenta text' + Style.ResetAll);
  WriteLn(Fore.White   + 'This is white text'   + Style.ResetAll);
  WriteLn(Fore.DarkGray + 'This is dark gray text' + Style.ResetAll);

  ReadLn;
end.

Die Funktion EnableANSIColorConsole aktiviert die ANSI-Unterstuetzung unter Windows 10+ (ueber ENABLE_VIRTUAL_TERMINAL_PROCESSING). Unter Linux ist dies nicht noetig, da Terminals ANSI nativ unterstuetzen. Der Aufruf ist idempotent: Er kann beliebig oft ohne Nebeneffekte aufgerufen werden.

Style.ResetAll setzt alle Attribute (Textfarbe, Hintergrund und Stil) auf die Standardwerte des Terminals zurueck. Es sollte immer am Ende jeder farbigen Zeile verwendet werden, um zu verhindern, dass die Farbe auf nachfolgende Zeilen “uebergreift”.

Jeder Record bietet 16 Farben, sowohl in den “Dark”-Varianten (ANSI-Codes 30-37 / 40-47) als auch in den Bright-Varianten (90-97 / 100-107):

Fore/Back Dark Bright
Red DarkRed (31/41) Red (91/101)
Green DarkGreen (32/42) Green (92/102)
Yellow DarkYellow (33/43) Yellow (93/103)
Blue DarkBlue (34/44) Blue (94/104)
Magenta DarkMagenta (35/45) Magenta (95/105)
Cyan DarkCyan (36/46) Cyan (96/106)
Gray Gray (37/47) White (97/107)
Black/Gray Black (30/40) DarkGray (90/100)

Verfuegbare Foreground-Farbpalette in MVCFramework.Console

Farbkomposition

Die wahre Staerke der API liegt in der Komposition. Da es sich um einfache Strings handelt, werden Farben mit dem +-Operator kombiniert:

// Foreground + Background
WriteLn(Fore.White + Back.DarkBlue + ' White on Blue ' + Style.ResetAll);
WriteLn(Fore.Black + Back.Yellow   + ' Black on Yellow ' + Style.ResetAll);
WriteLn(Fore.White + Back.DarkRed  + ' CRITICAL ERROR ' + Style.ResetAll);

// Style + Foreground
WriteLn(Style.Bright + Fore.Green + 'Bold green text' + Style.ResetAll);
WriteLn(Style.Dim    + Fore.Cyan  + 'Dimmed cyan text' + Style.ResetAll);

// Farben inline im Text
WriteLn(
  'Status: ' + Fore.Green + 'OK' + Style.ResetAll +
  ' | Items: ' + Fore.Cyan + '42' + Style.ResetAll +
  ' | Errors: ' + Fore.Red + '0' + Style.ResetAll
);

Es gibt keine Klasse, kein Objekt, keine Methode. Nur String-Konstanten und Verkettung. Der Compiler loest alles zur Compile-Zeit auf: null Overhead zur Laufzeit.

Komposition von Foreground-, Background-Farben und Stilen

Praktische Badges

Mit Fore + Back lassen sich farbige Badges fuer jede Art von strukturierter Ausgabe erstellen:

// Test result badges
WriteLn(Back.DarkGreen + Fore.White + ' PASS ' + Style.ResetAll + '  TestUserAuth');
WriteLn(Back.DarkRed   + Fore.White + ' FAIL ' + Style.ResetAll + '  TestPaymentTimeout');
WriteLn(Back.DarkYellow + Fore.White + ' SKIP ' + Style.ResetAll + '  TestExternalAPI');

// HTTP status badges
WriteLn(Fore.White + Back.DarkGreen  + ' 200 ' + Style.ResetAll + ' GET /api/people');
WriteLn(Fore.White + Back.DarkYellow + ' 404 ' + Style.ResetAll + ' GET /api/unknown');
WriteLn(Fore.White + Back.DarkRed    + ' 500 ' + Style.ResetAll + ' GET /api/crash');

Praktische Badges: Testergebnisse, HTTP-Status und Log-Level

Wiederverwendbare Stile definieren (wie CSS fuer die Konsole)

Fore.White + Back.DarkGreen jedes Mal zu wiederholen, wenn man ein gruenes Badge moechte, ist umstaendlich und fragil: Wenn man morgen das Gruen in Cyan aendern will, muss man jede Stelle anpassen. Die Loesung ist simpel, aber wirkungsvoll: Man definiert einfach Konstanten.

const
  STYLE_SUCCESS = Fore.White + Back.DarkGreen;
  STYLE_ERROR   = Fore.White + Back.DarkRed;
  STYLE_WARNING = Fore.White + Back.DarkYellow;
  STYLE_INFO    = Fore.White + Back.DarkBlue;
  STYLE_MUTED   = Fore.DarkGray;
  STYLE_RESET   = Style.ResetAll;

Damit wird der Code sauber und lesbar, genau wie das Anwenden von CSS-Klassen auf HTML-Elemente:

WriteLn(STYLE_SUCCESS + ' DONE ' + STYLE_RESET + ' Database migration completed');
WriteLn(STYLE_WARNING + ' SLOW ' + STYLE_RESET + ' Query took 3.2s on table Orders');
WriteLn(STYLE_ERROR   + ' FAIL ' + STYLE_RESET + ' Connection refused on port 5432');
WriteLn(STYLE_INFO    + ' NOTE ' + STYLE_RESET + ' Using fallback configuration');
WriteLn(STYLE_MUTED + '--- end of report ---' + STYLE_RESET);

Da es sich um String-Konstanten handelt, die zur Compile-Zeit aufgeloest werden, gibt es keinerlei Overhead: Der Compiler expandiert sie inline. Man erhaelt den Komfort eines zentralisierten Stils mit der Performance von hartkodierten Strings.

Gin-Style HTTP-Logs in DMVCFramework

Das eigentliche Killer-Feature ist der Renderer TMVCColorConsoleRenderer, inspiriert vom HTTP-Logger von Gin (dem populaeren Web-Framework fuer Go). Dieser Renderer ist standardmaessig aktiv in allen DMVCFramework-Konsolenanwendungen - es ist keine Konfiguration erforderlich.

Funktionsweise

Jede HTTP-Anfrage wird in einem strukturierten Format mit Farben geloggt:

TIME | TID | STATUS | DURATION | IP | METHOD "path"

Die Badges verwenden exakt dieselben ANSI-Codes wie der Gin-Quellcode:

Element Farbe ANSI-Code
Status 2xx White auf DarkGreen 97;42
Status 3xx DarkGray auf Gray 90;47
Status 4xx White auf DarkYellow 97;43
Status 5xx White auf DarkRed 97;41
GET White auf DarkBlue 97;44
POST White auf DarkCyan 97;46
PUT White auf DarkYellow 97;43
DELETE White auf DarkRed 97;41
PATCH White auf DarkGreen 97;42
HEAD White auf DarkMagenta 97;45

Gin-Style HTTP-Logs in einem DMVCFramework-Server

Anwendungsbezogene Log-Level

Nicht-HTTP-Logs (Anwendungsmeldungen) verwenden eigene Farben, die sich nicht mit den HTTP-Badges ueberschneiden:

Level Stil Logik
DEBUG Dunkelgrau Geringes visuelles Rauschen
INFO Blau Neutral, informativ
WARN Gelb Aufmerksamkeit
ERROR Rot fett Problem
FATAL Weisses Badge auf Rot Unmoeglich zu uebersehen

FATAL ist der einzige Anwendungs-Level mit farbigem Hintergrund: Als kritischster Level muss er auch in einem sehr dichten Log sofort ins Auge fallen.

LogD('Processing request...');       // DEBUG - grau, fast unsichtbar
LogI('Server started on port 8080'); // INFO  - blau, informativ
LogW('Cache miss rate above 50%');   // WARN  - gelb, Aufmerksamkeit
LogE('Connection to database lost'); // ERROR - rot fett, Problem
Log.Fatal('Out of memory', LOGGERPRO_TAG); // FATAL - rotes Badge, kritisch

Alle Log-Level: DEBUG, INFO, WARN, ERROR, FATAL

Farbige Konsole, saubere Dateien

Eine berechtigte Frage: Wenn die Konsolenlogs ANSI-Escape-Sequenzen enthalten, was passiert mit den Datei-Logs? Die Antwort lautet: Nichts. Das Logging-System von DMVCFramework basiert auf LoggerPro, das mehrere Appender unterstuetzt. Jeder Appender hat seinen eigenen Renderer: Der Konsolen-Appender verwendet TMVCColorConsoleRenderer fuer farbige Ausgabe, waehrend der Datei-Appender einen Standard-Text-Renderer verwendet. ANSI-Codes gelangen nie in die Log-Dateien - jedes Ziel erhaelt genau das passende Format.

Automatischer Fallback

Der Konsolen-Renderer erkennt automatisch, ob das Terminal ANSI-Farben unterstuetzt. Falls nicht (zum Beispiel unter Windows-Versionen vor 10), erzeugt er Klartext-Ausgabe ohne Escape-Sequenzen, identisch mit dem frueheren DMVCFramework-Format. Kein {$IFDEF} im Code erforderlich.

Anfragedauer

Jede HTTP-Anfrage enthaelt automatisch die Ausfuehrungszeit, gemessen mit TStopWatch aus System.Diagnostics. Der Overhead ist vernachlaessigbar (20-50 Nanosekunden pro Aufruf) und die Information ist wertvoll, um langsame Endpoints zu identifizieren.

Kompatibilitaet

Plattform Unterstuetzung
Windows 10+ Vollstaendig (ANSI via SetConsoleMode)
Windows < 10 Fallback auf Klartext
Linux Nativ (ANSI von allen Terminals unterstuetzt)

Jetzt ausprobieren

Der Quellcode der Beispiele ist im Ordner samples/console_colors* des GitHub-Repositories verfuegbar:

  • samples/console_colors_basics/ - Grundfarben
  • samples/console_colors_composition/ - Komposition und Stile
  • samples/console_colors_badges/ - Praktische Badges

Fuer die Gin-Style Logs ist nichts weiter noetig: Erstellen Sie einfach eine DMVCFramework-Konsolenanwendung und die farbigen Logs erscheinen automatisch.

// Das ist alles. Die Farben sind bereits aktiv.
program MyServer;
{$APPTYPE CONSOLE}
uses
  MVCFramework, MVCFramework.Console, MVCFramework.Logger;
begin
  // EnableANSIColorConsole wird automatisch vom Renderer aufgerufen
  // ... Ihr DMVC-Server
end.

Haeufig gestellte Fragen

Wie fuegt man Farben zur Konsole in Delphi hinzu? Verwenden Sie die Unit MVCFramework.Console und die Records Fore, Back, Style. Rufen Sie EnableANSIColorConsole am Anfang des Programms auf und kombinieren Sie dann die Farben durch Verkettung: WriteLn(Fore.Red + 'roter Text' + Style.ResetAll).

Funktioniert es unter Windows? Ja, unter Windows 10 und neuer. Die Funktion EnableANSIColorConsole aktiviert die ANSI-Unterstuetzung ueber SetConsoleMode. Unter aelteren Versionen erzeugt der Renderer automatisch Klartext-Ausgabe.

Kann man die Farben ohne DMVCFramework verwenden? Ja. Die Unit MVCFramework.Console.pas hat keine Abhaengigkeiten vom Framework. Sie koennen sie in jedes beliebige Delphi-Konsolenprojekt kopieren.

Gelangen die ANSI-Codes in die Log-Dateien? Nein. DMVCFramework verwendet LoggerPro mit mehreren Appendern: Der Konsolen-Appender nutzt den farbigen Renderer, der Datei-Appender einen Standard-Text-Renderer. Jedes Ziel erhaelt das passende Format.

Wie gross ist der Overhead der Zeitmessung? Vernachlaessigbar. TStopWatch benoetigt 20-50 Nanosekunden pro Aufruf, irrelevant im Vergleich zur Verarbeitungszeit einer beliebigen HTTP-Anfrage.

Comments

comments powered by Disqus