Shuffle/app/lib/core/logging/app_logger.dart
cschlaefke 25212929ce
All checks were successful
CI / flutter (pull_request) Successful in 1m46s
CI / web-build (pull_request) Successful in 59s
CI / supabase (pull_request) Successful in 12s
CI / supabase-tests (pull_request) Successful in 31s
CI / e2e (pull_request) Successful in 2m54s
feat(catalog): review fixes for catalog search
Word limit and no-retry state for rejected input, nested /catalog route for
system back, logger filter for supabase libs, more mutation-proof tests,
doc fix, umlaut-aware term sorting, thousands separators. Refs #3

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-04 10:17:54 +01:00

71 lines
2.3 KiB
Dart

import 'dart:async';
import 'dart:developer' as developer;
import 'package:flutter/foundation.dart';
import 'package:logging/logging.dart';
/// Zentrales Logger-Utility (Wrapper um `package:logging`).
///
/// Regeln: kein `print`, keine personenbezogenen Daten (E-Mail, Namen,
/// Passwörter, Tokens) in Nachrichten oder Fehlerobjekten.
class AppLogger {
AppLogger(String name) : _logger = Logger(name);
final Logger _logger;
void debug(String message) => _logger.fine(message);
void info(String message) => _logger.info(message);
void warning(String message, {Object? error, StackTrace? stackTrace}) =>
_logger.warning(message, error, stackTrace);
void error(String message, {Object? error, StackTrace? stackTrace}) =>
_logger.severe(message, error, stackTrace);
static StreamSubscription<LogRecord>? _subscription;
/// Richtet die Ausgabe ein. Release: ab INFO, sonst alles.
///
/// Idempotent: Wiederholte Aufrufe aktualisieren nur den Level und
/// registrieren keinen weiteren Listener.
///
/// Hinweis: `developer.log` hat in Release-Builds praktisch keine sichtbare
/// Wirkung; produktives Crash-/Error-Reporting folgt in einem eigenen Task.
static void configure({Level? level}) {
Logger.root.level = level ?? (kReleaseMode ? Level.INFO : Level.ALL);
_subscription ??= Logger.root.onRecord.listen(_write);
}
/// Aktiver Listener (nur für Tests).
@visibleForTesting
static StreamSubscription<LogRecord>? get subscription => _subscription;
/// Entfernt den Listener wieder (nur für Tests).
@visibleForTesting
static Future<void> resetForTesting() async {
await _subscription?.cancel();
_subscription = null;
}
/// Whether a record is written. Records of the Supabase libraries below
/// INFO are dropped: postgrest logs `'$error from request'` at FINE, and the
/// error text can echo request parameters (search terms, QUE-04).
@visibleForTesting
static bool shouldWrite(LogRecord record) =>
!(record.loggerName.startsWith('supabase') && record.level < Level.INFO);
static void _write(LogRecord record) {
if (!shouldWrite(record)) {
return;
}
developer.log(
record.message,
time: record.time,
level: record.level.value,
name: record.loggerName,
error: record.error,
stackTrace: record.stackTrace,
);
}
}