380 lines
16 KiB
C#
380 lines
16 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
|
|
namespace Project_Periodensystem.Model
|
|
{
|
|
/// <summary>
|
|
/// Zentrale Logging-Klasse für Debug-Ausgaben und Fehlerprotokollierung
|
|
///
|
|
/// ZWECK UND ARCHITEKTUR:
|
|
/// - Einheitliche Logging-Infrastruktur für die gesamte Anwendung
|
|
/// - Dual-Output: Konsole (Development) und Datei (Production/Debugging)
|
|
/// - Verschiedene Log-Level für strukturierte Protokollierung
|
|
/// - Demonstration verschiedener C#-Konzepte und Datentypen
|
|
///
|
|
/// DESIGN PATTERNS:
|
|
/// - Static Class: Globaler Zugriff ohne Instanziierung
|
|
/// - Facade Pattern: Vereinfachte API für komplexe Logging-Operationen
|
|
/// - Strategy Pattern: Verschiedene Ausgabekanäle (Konsole, Datei)
|
|
///
|
|
/// C# KONZEPTE:
|
|
/// - Static Constructor: Einmalige Initialisierung beim ersten Zugriff
|
|
/// - Exception Handling: Try-Catch für robuste Datei-Operationen
|
|
/// - Method Overloading: Verschiedene LogArray-Varianten
|
|
/// - Conditional Compilation: [Conditional("DEBUG")] für LogDebug
|
|
/// - LINQ: Select() für Datenformatierung
|
|
/// - String Interpolation: $"Text {variable}" für lesbare Ausgaben
|
|
///
|
|
/// SICHERHEIT UND ROBUSTHEIT:
|
|
/// - Alle Datei-Operationen sind exception-safe
|
|
/// - Logging-Fehler bringen die Hauptanwendung nicht zum Absturz
|
|
/// - Graceful Degradation bei fehlenden Dateiberechtigungen
|
|
/// </summary>
|
|
public static class Logger
|
|
{
|
|
/// <summary>
|
|
/// Pfad zur Log-Datei im lokalen Anwendungsverzeichnis
|
|
///
|
|
/// PFAD-KONSTRUKTION:
|
|
/// - Environment.SpecialFolder.LocalApplicationData: Benutzer-spezifischer App-Ordner
|
|
/// - Windows: C:\Users\[Username]\AppData\Local\Periodensystem\app.log
|
|
/// - Cross-Platform: Funktioniert auf Windows, Linux, macOS
|
|
///
|
|
/// C# KONZEPTE:
|
|
/// - Path.Combine(): Sichere Pfad-Konstruktion (OS-unabhängig)
|
|
/// - Environment.SpecialFolder: Standard-Verzeichnisse des Betriebssystems
|
|
/// - Readonly Field: Kann nur bei Deklaration oder im static Constructor gesetzt werden
|
|
/// </summary>
|
|
private static readonly string LogFilePath = Path.Combine(
|
|
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
|
"Periodensystem", "app.log");
|
|
|
|
/// <summary>
|
|
/// Statischer Konstruktor - Einmalige Initialisierung der Logger-Infrastruktur
|
|
///
|
|
/// ZWECK:
|
|
/// - Erstellt das Log-Verzeichnis falls es nicht existiert
|
|
/// - Wird automatisch beim ersten Zugriff auf die Klasse aufgerufen
|
|
/// - Kann nicht explizit aufgerufen werden
|
|
///
|
|
/// C# KONZEPTE:
|
|
/// - Static Constructor: Automatische Initialisierung ohne Parameter
|
|
/// - Path.GetDirectoryName(): Extrahiert Verzeichnis aus vollständigem Pfad
|
|
/// - Directory.CreateDirectory(): Erstellt Verzeichnis-Hierarchie rekursiv
|
|
/// - Exception Handling: Fehler werden "geschluckt" für Robustheit
|
|
///
|
|
/// FEHLERBEHANDLUNG:
|
|
/// - Bei Problemen wird nur Konsolen-Logging verwendet
|
|
/// - Keine Exception nach außen, da Logging optional ist
|
|
/// </summary>
|
|
static Logger()
|
|
{
|
|
try
|
|
{
|
|
var logDirectory = Path.GetDirectoryName(LogFilePath);
|
|
if (logDirectory != null && !Directory.Exists(logDirectory))
|
|
{
|
|
Directory.CreateDirectory(logDirectory);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// Falls Log-Datei nicht erstellt werden kann, nur Konsole verwenden
|
|
// Graceful Degradation: Hauptfunktionalität nicht beeinträchtigen
|
|
}
|
|
}
|
|
|
|
// ===== HAUPTPROTOKOLLIERUNGS-METHODEN =====
|
|
|
|
/// <summary>
|
|
/// Zentrale Logging-Methode - protokolliert Nachrichten dual (Konsole + Datei)
|
|
///
|
|
/// ZWECK:
|
|
/// - Universelle Protokollierung für alle Anwendungsereignisse
|
|
/// - Entwickler sehen Ausgaben in Konsole (sofortiges Feedback)
|
|
/// - Benutzer/Support kann Logs aus Datei analysieren
|
|
///
|
|
/// C# KONZEPTE:
|
|
/// - String.IsNullOrWhiteSpace(): Robuste Null/Empty/Whitespace-Prüfung
|
|
/// - DateTime.Now.ToString(): Formatierte Zeitstempel
|
|
/// - String Interpolation: $"[{timestamp}] {message}"
|
|
/// - File.AppendAllText(): Atomare Datei-Operation
|
|
/// - Environment.NewLine: OS-spezifische Zeilentrenner
|
|
///
|
|
/// FEHLERBEHANDLUNG:
|
|
/// - Guard Clause: Leere Nachrichten werden ignoriert
|
|
/// - Try-Catch um Datei-Operation: Konsole funktioniert immer
|
|
/// - Keine Exception nach außen: Logging darf nie Hauptanwendung stören
|
|
///
|
|
/// THREAD-SAFETY:
|
|
/// - File.AppendAllText ist thread-safe
|
|
/// - Console.WriteLine ist thread-safe
|
|
/// - Methode kann von mehreren Threads gleichzeitig aufgerufen werden
|
|
/// </summary>
|
|
/// <param name="message">Zu protokollierende Nachricht (wird validiert)</param>
|
|
public static void Log(string message)
|
|
{
|
|
// Guard Clause: Ungültige Eingaben frühzeitig abfangen
|
|
if (string.IsNullOrWhiteSpace(message))
|
|
return;
|
|
|
|
// Zeitstempel im ISO-ähnlichen Format für bessere Lesbarkeit
|
|
var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
|
var logEntry = $"[{timestamp}] {message}";
|
|
|
|
// Konsolen-Ausgabe (für Entwicklung und sofortiges Feedback)
|
|
Console.WriteLine(logEntry);
|
|
|
|
// Datei-Ausgabe (für Persistenz und spätere Analyse)
|
|
try
|
|
{
|
|
File.AppendAllText(LogFilePath, logEntry + Environment.NewLine);
|
|
}
|
|
catch
|
|
{
|
|
// Fehler beim Schreiben ignorieren um App nicht zum Absturz zu bringen
|
|
// Silent Fail: Logging ist nice-to-have, nicht essential
|
|
}
|
|
}
|
|
|
|
// ===== SPEZIALISIERTE LOGGING-METHODEN =====
|
|
|
|
/// <summary>
|
|
/// Protokolliert Exceptions mit vollständigen Diagnose-Informationen
|
|
///
|
|
/// ZWECK:
|
|
/// - Strukturierte Fehlerprotokollierung für Debugging
|
|
/// - Vollständige Stack-Trace-Information für Fehleranalyse
|
|
/// - Kontextuelle Information für bessere Problemlösung
|
|
///
|
|
/// C# KONZEPTE:
|
|
/// - Exception Handling: ex.Message und ex.StackTrace Properties
|
|
/// - Null-Check: Schutz vor null-Exceptions
|
|
/// - String Interpolation: Eingebettete Variablen in Strings
|
|
/// - Conditional Operator: condition ? valueIfTrue : valueIfFalse
|
|
/// - Multi-Line Strings: \n für Zeilenumbrüche
|
|
///
|
|
/// PARAMETER:
|
|
/// - ex: Die zu protokollierende Exception (kann theoretisch null sein)
|
|
/// - context: Optional - zusätzlicher Kontext (Methodenname, Operation, etc.)
|
|
///
|
|
/// VERWENDUNG:
|
|
/// try { riskyOperation(); } catch (Exception ex) { Logger.LogException(ex, "DataLoad"); }
|
|
/// </summary>
|
|
/// <param name="ex">Exception die protokolliert werden soll</param>
|
|
/// <param name="context">Zusätzlicher Kontext (Methodenname, Operation, etc.)</param>
|
|
public static void LogException(Exception ex, string context = "")
|
|
{
|
|
// Null-Schutz: Auch ungültige Exception-Objekte handhaben
|
|
if (ex == null)
|
|
{
|
|
Log("Null-Exception übergeben - möglicher Programmierfehler");
|
|
return;
|
|
}
|
|
|
|
// Formatierung je nach verfügbarem Kontext
|
|
var message = string.IsNullOrWhiteSpace(context)
|
|
? $"EXCEPTION: {ex.Message}\nStack: {ex.StackTrace}"
|
|
: $"EXCEPTION in {context}: {ex.Message}\nStack: {ex.StackTrace}";
|
|
|
|
Log(message);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Protokolliert Warnungen - für nicht-kritische Probleme
|
|
///
|
|
/// ZWECK:
|
|
/// - Kennzeichnung von Problemen die behoben werden sollten
|
|
/// - Unterscheidung von Informationen und echten Fehlern
|
|
/// - Monitoring von potentiellen Problemen
|
|
///
|
|
/// BEISPIELE:
|
|
/// - Veraltete API-Aufrufe
|
|
/// - Performance-Probleme
|
|
/// - Unerwartete aber handhabbare Situationen
|
|
/// </summary>
|
|
/// <param name="message">Warnung (wird mit WARNING: Präfix versehen)</param>
|
|
public static void LogWarning(string message)
|
|
{
|
|
Log($"WARNING: {message}");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Protokolliert Fehler - für schwerwiegende Probleme
|
|
///
|
|
/// ZWECK:
|
|
/// - Kennzeichnung von Fehlern die Funktionalität beeinträchtigen
|
|
/// - Höhere Priorität als Warnings bei Log-Analyse
|
|
/// - Monitoring von kritischen Problemen
|
|
///
|
|
/// BEISPIELE:
|
|
/// - Datenverlust oder Corruption
|
|
/// - Netzwerk-/Datenbankfehler
|
|
/// - Konfigurationsprobleme
|
|
/// </summary>
|
|
/// <param name="message">Fehlermeldung (wird mit ERROR: Präfix versehen)</param>
|
|
public static void LogError(string message)
|
|
{
|
|
Log($"ERROR: {message}");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Protokolliert Debug-Informationen - nur in Debug-Builds kompiliert
|
|
///
|
|
/// ZWECK:
|
|
/// - Detaillierte Entwicklungs-Informationen
|
|
/// - Automatische Entfernung in Release-Builds
|
|
/// - Performance-Optimierung (keine Debug-Logs in Production)
|
|
///
|
|
/// C# KONZEPTE:
|
|
/// - Conditional Compilation: [Conditional("DEBUG")]
|
|
/// - Attribute-based Programming: Verhalten durch Metadaten steuern
|
|
/// - Build Configuration: Unterschiedliches Verhalten je nach Build-Typ
|
|
///
|
|
/// COMPILER-VERHALTEN:
|
|
/// - Debug Build: Methode wird normal ausgeführt
|
|
/// - Release Build: Methoden-Aufrufe werden vollständig entfernt
|
|
/// - Zero Performance Impact in Production
|
|
/// </summary>
|
|
/// <param name="message">Debug-Nachricht (wird mit DEBUG: Präfix versehen)</param>
|
|
[System.Diagnostics.Conditional("DEBUG")]
|
|
public static void LogDebug(string message)
|
|
{
|
|
Log($"DEBUG: {message}");
|
|
}
|
|
|
|
// ===== DATEI-MANAGEMENT UND UTILITY-METHODEN =====
|
|
|
|
/// <summary>
|
|
/// Löscht die Log-Datei für Cleanup-Operationen
|
|
///
|
|
/// ZWECK:
|
|
/// - Speicherplatz freigeben bei großen Log-Dateien
|
|
/// - Fresh Start für neue Test-Sessions
|
|
/// - Maintenance-Operation für Anwendungs-Lifecycle
|
|
///
|
|
/// C# KONZEPTE:
|
|
/// - File.Exists(): Existenz-Prüfung vor Operation
|
|
/// - File.Delete(): Atomare Datei-Löschung
|
|
/// - Exception Handling: Robust gegen Berechtigungsprobleme
|
|
///
|
|
/// SICHERHEIT:
|
|
/// - Prüft Existenz vor Löschung (vermeidet FileNotFoundException)
|
|
/// - Catch für Berechtigungsfehler oder Datei-in-Verwendung
|
|
/// - Loggt eigene Operationen (self-documenting)
|
|
/// </summary>
|
|
public static void ClearLog()
|
|
{
|
|
try
|
|
{
|
|
if (File.Exists(LogFilePath))
|
|
{
|
|
File.Delete(LogFilePath);
|
|
Log("Log-Datei gelöscht und neu initialisiert");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log($"Fehler beim Löschen der Log-Datei: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt den vollständigen Pfad zur Log-Datei zurück
|
|
///
|
|
/// ZWECK:
|
|
/// - Ermöglicht externen Tools Zugriff auf Log-Datei
|
|
/// - Debugging: Entwickler kann Log-Datei manuell öffnen
|
|
/// - Integration: Andere Komponenten können Logs lesen
|
|
///
|
|
/// KAPSELUNG:
|
|
/// - Kontrollierter Zugriff auf private LogFilePath
|
|
/// - Readonly-Zugriff: Externe Komponenten können Pfad nicht ändern
|
|
/// - Information Hiding: Implementation Details bleiben verborgen
|
|
/// </summary>
|
|
/// <returns>Vollständiger Pfad zur Log-Datei (absoluter Pfad)</returns>
|
|
public static string GetLogFilePath()
|
|
{
|
|
return LogFilePath;
|
|
}
|
|
|
|
// ===== SPEZIALISIERTE DATENTYP-LOGGING (C# LERNZWECK) =====
|
|
|
|
/// <summary>
|
|
/// Loggt String-Arrays - demonstriert Array-Verarbeitung
|
|
///
|
|
/// ZWECK:
|
|
/// - Zeigt Array-Inhalte in lesbarer Form
|
|
/// - Demonstriert string.Join() für Array-zu-String-Konvertierung
|
|
/// - Nützlich für Listen von Elementsymbolen, Namen, etc.
|
|
///
|
|
/// C# KONZEPTE:
|
|
/// - Method Overloading: Mehrere LogArray-Methoden für verschiedene Typen
|
|
/// - string.Join(): Elegante Array-zu-String-Konvertierung
|
|
/// - Array-Parameter: string[] als Eingabe
|
|
///
|
|
/// BEISPIEL-AUSGABE:
|
|
/// "Element-Symbole: [H, He, Li, Be, B, C, N, O, F, Ne]"
|
|
/// </summary>
|
|
/// <param name="title">Beschreibender Titel für das Array</param>
|
|
/// <param name="items">Array von Strings zur Anzeige</param>
|
|
public static void LogArray(string title, string[] items)
|
|
{
|
|
Log($"{title}: [{string.Join(", ", items)}]");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Loggt Double-Arrays - demonstriert numerische Array-Verarbeitung
|
|
///
|
|
/// ZWECK:
|
|
/// - Zeigt numerische Daten in formatierter Form
|
|
/// - Demonstriert LINQ Select() für Datenformatierung
|
|
/// - Nützlich für Atomgewichte, Dichten, Elektronegativitäten
|
|
///
|
|
/// C# KONZEPTE:
|
|
/// - LINQ Select(): Funktionale Programmierung für Datentransformation
|
|
/// - Lambda Expression: n => n.ToString("F2") für Formatierung
|
|
/// - ToString() mit Format-String: "F2" für 2 Dezimalstellen
|
|
/// - Method Overloading: Verschiedene Typen, gleicher Methodenname
|
|
///
|
|
/// BEISPIEL-AUSGABE:
|
|
/// "Atomgewichte: [1.01, 4.00, 6.94, 9.01, 10.81]"
|
|
/// </summary>
|
|
/// <param name="title">Beschreibender Titel für das Array</param>
|
|
/// <param name="numbers">Array von Double-Werten zur Anzeige</param>
|
|
public static void LogArray(string title, double[] numbers)
|
|
{
|
|
// LINQ Select() wandelt jede Zahl in formatierten String um
|
|
var formattedNumbers = numbers.Select(n => n.ToString("F2")).ToArray();
|
|
Log($"{title}: [{string.Join(", ", formattedNumbers)}]");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Loggt Tuple-Informationen - demonstriert strukturierte Datenausgabe
|
|
///
|
|
/// ZWECK:
|
|
/// - Zeigt Tuple-Inhalte in lesbarer Form
|
|
/// - Demonstriert strukturierte Datenprotokollierung
|
|
/// - Nützlich für Element-Statistiken und zusammengehörige Werte
|
|
///
|
|
/// C# KONZEPTE:
|
|
/// - Tuple: Strukturierte Datencontainer
|
|
/// - String als Parameter: Bereits formatierte Tuple-Darstellung
|
|
/// - Delegation: Ruft zentrale Log()-Methode auf
|
|
///
|
|
/// VERWENDUNG:
|
|
/// var stats = GetStatistics(); // returns (int, int, double)
|
|
/// Logger.LogTuple("Statistiken", $"Elemente: {stats.Item1}, Serien: {stats.Item2}");
|
|
///
|
|
/// BEISPIEL-AUSGABE:
|
|
/// "Element-Info: Symbol: H, Name: Hydrogen, Gewicht: 1.01"
|
|
/// </summary>
|
|
/// <param name="title">Beschreibender Titel für das Tuple</param>
|
|
/// <param name="tupleInfo">Bereits formatierte Tuple-Darstellung als String</param>
|
|
public static void LogTuple(string title, string tupleInfo)
|
|
{
|
|
Log($"{title}: {tupleInfo}");
|
|
}
|
|
}
|
|
} |