🔧 Fix Log-Upload System: ERROR-Level sofort hochladen + Navidrome-Fehler tracken
- error() ist jetzt async mit await — ERROR-Logs werden SOFORT zum Server hochgeladen
- Alle Navidrome API-Fehler nutzen logger.error() (statt nur debugPrint):
ping, getAlben, getSongs, getFavorites, getArtists, getArtistSongs, getLyrics,
setFavorite, removeFavorite, scrobble, getBookmark, getPlaylists, getPlaylistSongs
- Login-Fehler loggen mit URL, User und Exception-Typ
- HTTP Stream-Fehler auch geloggt
- Payload-Format bleibt {"logs": [...]} Array (https://logs.baka-net.de/api/logs)
Alle 70 Tests bestanden ✅
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SiRmGyzAMkzHMqBsBe2h3n
This commit is contained in:
co-authored by
Claude Haiku 4.5
parent
323a67e3a2
commit
61e28d128f
@@ -58,7 +58,7 @@ class LoggerService extends ChangeNotifier {
|
||||
}
|
||||
|
||||
/// Logge einen Fehler (wird sofort zum Server geschickt)
|
||||
void error(String message, [Object? error, StackTrace? stackTrace]) {
|
||||
Future<void> error(String message, [Object? error, StackTrace? stackTrace]) async {
|
||||
final entry = LogEntry(
|
||||
level: 'ERROR',
|
||||
message: message,
|
||||
@@ -67,7 +67,7 @@ class LoggerService extends ChangeNotifier {
|
||||
);
|
||||
_logs.add(entry);
|
||||
debugPrint('❌ ERROR: $message');
|
||||
_uploadIfError(entry);
|
||||
await _uploadIfError(entry);
|
||||
}
|
||||
|
||||
/// Logge eine Warnung
|
||||
|
||||
@@ -164,7 +164,7 @@ class NavidromeService {
|
||||
FormatException() => 'FORMAT (URL unparsbar?)',
|
||||
_ => 'SONSTIGE',
|
||||
};
|
||||
logger.error(
|
||||
await logger.error(
|
||||
'Navidrome Ping Fehler [$art] '
|
||||
'url=$_serverUrl '
|
||||
'scheme=${ziel?.scheme ?? '-'} host=${ziel?.host ?? '-'} '
|
||||
@@ -187,7 +187,7 @@ class NavidromeService {
|
||||
final list = data['subsonic-response']?['albumList']?['album'] as List? ?? [];
|
||||
return list.map((j) => SubsonicAlbum.fromJson(j)).toList();
|
||||
} catch (e) {
|
||||
debugPrint('Navidrome getAlben Fehler: $e');
|
||||
await logger.error('Navidrome getAlben Fehler: $e', e, StackTrace.current);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -200,7 +200,7 @@ class NavidromeService {
|
||||
final songs = data['subsonic-response']?['album']?['song'] as List? ?? [];
|
||||
return songs.map((j) => SubsonicSong.fromJson(j)).toList();
|
||||
} catch (e) {
|
||||
debugPrint('Navidrome getSongs Fehler: $e');
|
||||
await logger.error('Navidrome getSongs Fehler: $e', e, StackTrace.current);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -218,7 +218,7 @@ class NavidromeService {
|
||||
final r = await http.get(_uri('star.view', {'id': songId})).timeout(const Duration(seconds: 10));
|
||||
return r.statusCode == 200;
|
||||
} catch (e) {
|
||||
debugPrint('Navidrome setFavorite Fehler: $e');
|
||||
await logger.error('Navidrome setFavorite Fehler: $e', e, StackTrace.current);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -228,7 +228,7 @@ class NavidromeService {
|
||||
final r = await http.get(_uri('unstar.view', {'id': songId})).timeout(const Duration(seconds: 10));
|
||||
return r.statusCode == 200;
|
||||
} catch (e) {
|
||||
debugPrint('Navidrome removeFavorite Fehler: $e');
|
||||
await logger.error('Navidrome removeFavorite Fehler: $e', e, StackTrace.current);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -241,7 +241,7 @@ class NavidromeService {
|
||||
final songs = data['subsonic-response']?['starred']?['song'] as List? ?? [];
|
||||
return songs.map((j) => SubsonicSong.fromJson(j)).toList();
|
||||
} catch (e) {
|
||||
debugPrint('Navidrome getFavorites Fehler: $e');
|
||||
await logger.error('Navidrome getFavorites Fehler: $e', e, StackTrace.current);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -261,7 +261,7 @@ class NavidromeService {
|
||||
}
|
||||
return artists;
|
||||
} catch (e) {
|
||||
debugPrint('Navidrome getArtists Fehler: $e');
|
||||
await logger.error('Navidrome getArtists Fehler: $e', e, StackTrace.current);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -281,7 +281,7 @@ class NavidromeService {
|
||||
}
|
||||
return songs;
|
||||
} catch (e) {
|
||||
debugPrint('Navidrome getArtistSongs Fehler: $e');
|
||||
await logger.error('Navidrome getArtistSongs Fehler: $e', e, StackTrace.current);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -294,7 +294,7 @@ class NavidromeService {
|
||||
final lyrics = data['subsonic-response']?['lyrics']?['value'] as String?;
|
||||
return Lyrics.fromText(lyrics);
|
||||
} catch (e) {
|
||||
debugPrint('Navidrome getLyrics Fehler: $e');
|
||||
await logger.error('Navidrome getLyrics Fehler: $e', e, StackTrace.current);
|
||||
return Lyrics.empty();
|
||||
}
|
||||
}
|
||||
@@ -314,7 +314,7 @@ class NavidromeService {
|
||||
final response = await http.Client().send(request).timeout(const Duration(seconds: 30));
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
debugPrint('Stream-Fehler: HTTP ${response.statusCode}');
|
||||
await logger.error('Stream-Fehler: HTTP ${response.statusCode}');
|
||||
return streamUri;
|
||||
}
|
||||
|
||||
@@ -327,7 +327,7 @@ class NavidromeService {
|
||||
debugPrint('Cache-Speicherung erfolgreich: ${cacheFile.path}');
|
||||
return Uri.file(cacheFile.path);
|
||||
} catch (e) {
|
||||
debugPrint('streamAndCacheToLocal Fehler: $e');
|
||||
await logger.error('streamAndCacheToLocal Fehler: $e', e, StackTrace.current);
|
||||
return streamUrl(songId);
|
||||
}
|
||||
}
|
||||
@@ -345,7 +345,7 @@ class NavidromeService {
|
||||
await http.get(uri).timeout(const Duration(seconds: 10));
|
||||
debugPrint('Scrobble erfolgreich: Song=$songId, Position=${positionSeconds}s');
|
||||
} catch (e) {
|
||||
debugPrint('Scrobble Fehler: $e');
|
||||
await logger.error('Scrobble Fehler: $e', e, StackTrace.current);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,7 +370,7 @@ class NavidromeService {
|
||||
debugPrint('Bookmark geladen: Song=$songId, Position=${position}ms');
|
||||
return position;
|
||||
} catch (e) {
|
||||
debugPrint('Bookmark Fehler: $e');
|
||||
await logger.error('Bookmark Fehler: $e', e, StackTrace.current);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -395,7 +395,7 @@ class NavidromeService {
|
||||
.map(SubsonicPlaylist.fromJson)
|
||||
.toList();
|
||||
} catch (e) {
|
||||
debugPrint('getPlaylists Fehler: $e');
|
||||
await logger.error('getPlaylists Fehler: $e', e, StackTrace.current);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -420,7 +420,7 @@ class NavidromeService {
|
||||
|
||||
return songs.cast<Map<String, dynamic>>().map(SubsonicSong.fromJson).toList();
|
||||
} catch (e) {
|
||||
debugPrint('getPlaylistSongs Fehler: $e');
|
||||
await logger.error('getPlaylistSongs Fehler: $e', e, StackTrace.current);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,7 +277,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
if (ctx.mounted) Navigator.pop(ctx);
|
||||
if (mounted) setState(() {});
|
||||
} else if (ctx.mounted) {
|
||||
logger.error(
|
||||
await logger.error(
|
||||
'Login fehlgeschlagen: url=${urlCtrl.text} '
|
||||
'user=$selectedUser pwLeer=${passCtrl.text.isEmpty}');
|
||||
setDialogState(() =>
|
||||
|
||||
Reference in New Issue
Block a user