diff --git a/.gitea/workflows/code-quality.yaml b/.gitea/workflows/code-quality.yaml index 8c35d11..dc69eb5 100644 --- a/.gitea/workflows/code-quality.yaml +++ b/.gitea/workflows/code-quality.yaml @@ -24,16 +24,14 @@ jobs: components: clippy, rustfmt cache: false + # Ein rohes 'actions/cache' auf target/ liefert zwar einen technischen Cache-Hit (Dateien + # werden wiederhergestellt), Cargo kompiliert die Abhängigkeiten aber oft trotzdem neu: + # Der tar-basierte Restore-Vorgang setzt bei allen wiederhergestellten Dateien dieselbe + # Mtime, wodurch Cargos Fingerprinting nicht mehr zuverlässig erkennen kann, was + # älter/neuer als was ist, und sicherheitshalber alles neu baut. Swatinem/rust-cache ist + # genau dafür gebaut (u. a. gezielte Mtime-Korrektur nach dem Restore). - name: Cache Cargo-Abhängigkeiten & Build-Artefakte - uses: actions/cache@v6 - with: - path: | - ~/.cargo/registry - ~/.cargo/git - target - key: cargo-${{ runner.os }}-${{ hashFiles('Cargo.lock') }} - restore-keys: | - cargo-${{ runner.os }}- + uses: Swatinem/rust-cache@v2 - name: Formatierung automatisch beheben run: cargo fmt diff --git a/.gitea/workflows/main.yaml b/.gitea/workflows/main.yaml index 8157f26..6db7dcb 100644 --- a/.gitea/workflows/main.yaml +++ b/.gitea/workflows/main.yaml @@ -54,16 +54,14 @@ jobs: toolchain: stable cache: false + # Ein rohes 'actions/cache' auf target/ liefert zwar einen technischen Cache-Hit (Dateien + # werden wiederhergestellt), Cargo kompiliert die Abhängigkeiten aber oft trotzdem neu: + # Der tar-basierte Restore-Vorgang setzt bei allen wiederhergestellten Dateien dieselbe + # Mtime, wodurch Cargos Fingerprinting nicht mehr zuverlässig erkennen kann, was + # älter/neuer als was ist, und sicherheitshalber alles neu baut. Swatinem/rust-cache ist + # genau dafür gebaut (u. a. gezielte Mtime-Korrektur nach dem Restore). - name: Cache Cargo-Abhängigkeiten & Build-Artefakte - uses: actions/cache@v6 - with: - path: | - ~/.cargo/registry - ~/.cargo/git - target - key: cargo-${{ runner.os }}-${{ hashFiles('Cargo.lock') }} - restore-keys: | - cargo-${{ runner.os }}- + uses: Swatinem/rust-cache@v2 - name: Run Tests run: | diff --git a/.gitea/workflows/renovate.yaml b/.gitea/workflows/renovate.yaml index ccbdcb2..3e3f23e 100644 --- a/.gitea/workflows/renovate.yaml +++ b/.gitea/workflows/renovate.yaml @@ -9,7 +9,7 @@ jobs: renovate: name: Dependency-Updates prüfen & Pull Requests erstellen runs-on: ubuntu-latest - container: ghcr.io/renovatebot/renovate:44.83.0 + container: ghcr.io/renovatebot/renovate:44.103.6 steps: - name: Renovate ausführen run: renovate diff --git a/.gitea/workflows/security-scan.yaml b/.gitea/workflows/security-scan.yaml index 75df4b3..040bef7 100644 --- a/.gitea/workflows/security-scan.yaml +++ b/.gitea/workflows/security-scan.yaml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest env: TRIVY_VERSION: "0.74.0" - OSV_SCANNER_VERSION: "2.5.1" + OSV_SCANNER_VERSION: "2.6.0" steps: - name: Checkout Repository uses: actions/checkout@v7 diff --git a/.gitea/workflows/testing.yaml b/.gitea/workflows/testing.yaml index 44e60dd..fbefcde 100644 --- a/.gitea/workflows/testing.yaml +++ b/.gitea/workflows/testing.yaml @@ -43,16 +43,14 @@ jobs: toolchain: stable cache: false + # Ein rohes 'actions/cache' auf target/ liefert zwar einen technischen Cache-Hit (Dateien + # werden wiederhergestellt), Cargo kompiliert die Abhängigkeiten aber oft trotzdem neu: + # Der tar-basierte Restore-Vorgang setzt bei allen wiederhergestellten Dateien dieselbe + # Mtime, wodurch Cargos Fingerprinting nicht mehr zuverlässig erkennen kann, was + # älter/neuer als was ist, und sicherheitshalber alles neu baut. Swatinem/rust-cache ist + # genau dafür gebaut (u. a. gezielte Mtime-Korrektur nach dem Restore). - name: Cache Cargo-Abhängigkeiten & Build-Artefakte - uses: actions/cache@v6 - with: - path: | - ~/.cargo/registry - ~/.cargo/git - target - key: cargo-${{ runner.os }}-${{ hashFiles('Cargo.lock') }} - restore-keys: | - cargo-${{ runner.os }}- + uses: Swatinem/rust-cache@v2 - name: Run Tests run: | diff --git a/.gitea/workflows/trufflehog-scan.yaml b/.gitea/workflows/trufflehog-scan.yaml index 5e4fcb6..c6457cd 100644 --- a/.gitea/workflows/trufflehog-scan.yaml +++ b/.gitea/workflows/trufflehog-scan.yaml @@ -12,7 +12,7 @@ jobs: name: TruffleHog runs-on: ubuntu-latest env: - TRUFFLEHOG_VERSION: "3.97.4" + TRUFFLEHOG_VERSION: "3.97.5" steps: - name: Checkout Repository uses: actions/checkout@v7 diff --git a/.gitea/workflows/unit-tests.yaml b/.gitea/workflows/unit-tests.yaml index 7703f7f..69175cb 100644 --- a/.gitea/workflows/unit-tests.yaml +++ b/.gitea/workflows/unit-tests.yaml @@ -8,6 +8,7 @@ on: - reopened branches: - testing + - dev jobs: test: @@ -23,16 +24,14 @@ jobs: toolchain: stable cache: false + # Ein rohes 'actions/cache' auf target/ liefert zwar einen technischen Cache-Hit (Dateien + # werden wiederhergestellt), Cargo kompiliert die Abhängigkeiten aber oft trotzdem neu: + # Der tar-basierte Restore-Vorgang setzt bei allen wiederhergestellten Dateien dieselbe + # Mtime, wodurch Cargos Fingerprinting nicht mehr zuverlässig erkennen kann, was + # älter/neuer als was ist, und sicherheitshalber alles neu baut. Swatinem/rust-cache ist + # genau dafür gebaut (u. a. gezielte Mtime-Korrektur nach dem Restore). - name: Cache Cargo-Abhängigkeiten & Build-Artefakte - uses: actions/cache@v6 - with: - path: | - ~/.cargo/registry - ~/.cargo/git - target - key: cargo-${{ runner.os }}-${{ hashFiles('Cargo.lock') }} - restore-keys: | - cargo-${{ runner.os }}- + uses: Swatinem/rust-cache@v2 - name: Run Tests run: cargo test diff --git a/.idea/Logger.iml b/.idea/Logger.iml index bbe0a70..1aed096 100644 --- a/.idea/Logger.iml +++ b/.idea/Logger.iml @@ -4,6 +4,7 @@ + diff --git a/Cargo.lock b/Cargo.lock index 2892bf2..6b1feb0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,7 +16,7 @@ checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "logger-ctdra" -version = "1.0.5" +version = "1.1.0" dependencies = [ "program-ctdra", "time", diff --git a/Cargo.toml b/Cargo.toml index ece5d05..93b814b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "logger-ctdra" -version = "1.0.5" +version = "1.1.0" edition = "2024" authors = ['DragonSlayer_14'] readme = "README.md" diff --git a/README.md b/README.md index 1c270f3..11aa0f2 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ - `Warn` (2) — Warnungen (Ausgabe auf `stdout` mit `[?]`-Präfix) - `Info` (3) — Betriebsinformationen (Ausgabe auf `stdout` mit `[i]`-Präfix) - `Debug` (4) — Diagnoseausgaben (Ausgabe auf `stdout` mit `[d]`-Präfix) +- **Farbige Terminalausgabe**: Jede Zeile wird je nach Schweregrad eingefärbt (`Error` rot, `Warn` gelb, `Info` grün, `Debug` cyan). Farben werden nur ausgegeben, wenn `stdout`/`stderr` ein echtes Terminal ist (keine Umleitung in Datei/Pipe), `NO_COLOR` nicht gesetzt ist und `TERM` nicht `dumb` ist. Die Logdatei enthält stets reinen Text ohne ANSI-Codes. - **Threadsicherheit**: Dateischreibzugriffe und Konfiguration sind thread-sicher serialisiert. - **Einheitliches Format**: `[Präfix][DD.MM.YYYY HH:MM:SS.mmm][LEVEL][Tag]: Nachricht` - **Flexible Konfiguration**: diff --git a/renovate.json b/renovate.json index 717bd4d..0bb42ae 100644 --- a/renovate.json +++ b/renovate.json @@ -1,29 +1,59 @@ { "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": ["config:recommended"], + "extends": [ + "config:recommended" + ], "timezone": "Europe/Berlin", - "schedule": ["before 6am on monday"], + "schedule": [ + "before 6am" + ], "baseBranchPatterns": [ "dev" ], "packageRules": [ { - "matchFileNames": [".gitea/workflows/**"], + "matchFileNames": [ + ".gitea/workflows/**" + ], "groupName": "Gitea Actions", "separateMajorMinor": false, "separateMinorPatch": false }, { - "matchManagers": ["cargo"], + "matchManagers": [ + "cargo" + ], "groupName": "Cargo Dependencies", "separateMajorMinor": false, "separateMinorPatch": false }, { - "matchManagers": ["dockerfile", "docker-compose"], + "matchManagers": [ + "dockerfile", + "docker-compose" + ], "groupName": "Docker-Images", "separateMajorMinor": false, "separateMinorPatch": false + }, + { + "description": "Patch-/Minor-/Digest-Updates automatisch mergen, sobald alle CI-Checks (inkl. Unit-Tests) erfolgreich sind - Major-Updates sind unten explizit ausgenommen (siehe nächste Regel).", + "matchUpdateTypes": [ + "patch", + "minor", + "digest", + "lockFileMaintenance" + ], + "automerge": true, + "automergeType": "pr", + "platformAutomerge": true + }, + { + "description": "Major-Updates immer manuell prüfen, da potenziell brechende Änderungen.", + "matchUpdateTypes": [ + "major" + ], + "automerge": false } ], "customManagers": [ diff --git a/src/lib.rs b/src/lib.rs index bea72bd..407afab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,7 +24,7 @@ use std::env; use std::fmt::{Display, Formatter}; use std::fs::{File, OpenOptions, create_dir_all}; -use std::io::Write; +use std::io::{IsTerminal, Write}; use std::path::PathBuf; use std::str::FromStr; use std::sync::atomic::{AtomicU8, Ordering}; @@ -156,6 +156,33 @@ pub fn set_log_dir(path: impl Into) { } } +/// ANSI-Escape-Sequenz zum Zurücksetzen der Textfarbe. +const ANSI_RESET: &str = "\x1b[0m"; + +/// Liefert die ANSI-Farbsequenz für den jeweiligen Schweregrad. +/// +/// Farben: `Error` -> Rot, `Warn` -> Gelb, `Info` -> Grün, `Debug` -> Cyan. +fn ansi_color(log_level: &LogLevel) -> &'static str { + match log_level { + LogLevel::Error => "\x1b[31m", + LogLevel::Warn => "\x1b[33m", + LogLevel::Info => "\x1b[32m", + LogLevel::Debug => "\x1b[36m", + } +} + +/// Prüft, ob Farbausgabe für den gegebenen Stream sinnvoll ist. +/// +/// Voraussetzungen: +/// - Der Stream muss ein echtes Terminal sein (`is_terminal`), keine Umleitung in eine Datei oder Pipe. +/// - Die Umgebungsvariable `NO_COLOR` darf nicht gesetzt sein (siehe ). +/// - `TERM` darf nicht auf `dumb` stehen. +fn color_supported(stream_is_terminal: bool) -> bool { + stream_is_terminal + && env::var_os("NO_COLOR").is_none() + && env::var("TERM").map(|term| term != "dumb").unwrap_or(true) +} + /// Formatiert eine Lognachricht mit Zeitstempel, Level, Tag und Präfix. /// /// Format: @@ -224,7 +251,13 @@ pub fn log(tag: &str, message: &str, log_level: LogLevel) { let formatted = format_message(tag, message, &log_level); if log_level == LogLevel::Error { - eprintln!("{}", formatted); + if color_supported(std::io::stderr().is_terminal()) { + eprintln!("{}{}{}", ansi_color(&log_level), formatted, ANSI_RESET); + } else { + eprintln!("{}", formatted); + } + } else if color_supported(std::io::stdout().is_terminal()) { + println!("{}{}{}", ansi_color(&log_level), formatted, ANSI_RESET); } else { println!("{}", formatted); }