import 'dart:async'; import 'dart:convert'; import 'dart:io'; // Capte les traces `dart:developer log()` de l'app en cours d'exécution. // // `flutter run` ne les imprime PAS sur stdout (elles partent au VM Service, pas à // stdout ni à logcat). Sans ce pont, tout ce que `NymeaService._log()` journalise est // invisible depuis le poste — donc les traces de locale, de télémétrie et d'écriture // aussi. // // Usage : dart vm_logs.dart ws://127.0.0.1:PORT/TOKEN=/ws Future main(List args) async { final uri = args.first; final ws = await WebSocket.connect(uri); var id = 0; void call(String method, [Map params = const {}]) { ws.add(jsonEncode({ 'jsonrpc': '2.0', 'id': (++id).toString(), 'method': method, 'params': params, })); } ws.listen((raw) { final m = jsonDecode(raw as String) as Map; if (m['method'] != 'streamNotify') return; final ev = (m['params'] as Map)['event'] as Map; final kind = ev['kind']; // L'heure de l'ENREGISTREMENT, pas celle de la réception : le VM Service livre // l'historique bufférisé d'un coup au moment du streamListen, et horodater à la // réception écraserait toute la chronologie sous une seule seconde. final micros = (ev['timestamp'] as num?)?.toInt(); final ts = micros == null ? '--:--:--' : DateTime.fromMillisecondsSinceEpoch(micros) .toIso8601String() .substring(11, 23); if (kind == 'Logging') { final rec = ev['logRecord'] as Map; final name = (rec['loggerName'] as Map?)?['valueAsString'] ?? ''; final msg = (rec['message'] as Map?)?['valueAsString'] ?? ''; print('$ts [$name] $msg'); } else if (kind == 'WriteEvent') { final bytes = ev['bytes'] as String?; if (bytes != null) { stdout.write('$ts [stdout] ${utf8.decode(base64.decode(bytes))}'); } } }); call('streamListen', {'streamId': 'Logging'}); call('streamListen', {'streamId': 'Stdout'}); call('streamListen', {'streamId': 'Stderr'}); print('--- branché sur $uri ---'); await Future.delayed(const Duration(hours: 2)); }