// Firebase alapú log service — Crashlytics + Analytics // // Crashlytics: breadcrumb log, hiba rögzítés, egyedi attribútumok // Analytics: egyedi esemény tracking (warning-ok, hibák, fontos események) // // Éles appban is működik — kiegészíti az AppLogger-t (ami csak debug módban fut) // // Használat: // FirebaseLogger.i('startRecording', 'Track indítva: $name'); // FirebaseLogger.w('_onPosition', 'Ugrás kiszűrve: ${dist}m'); // FirebaseLogger.e('positionStream', 'GPS hiba', error: e, stack: s); // FirebaseLogger.event('track_completed', {'distance_m': 3200, 'points': 142}); import 'package:firebase_analytics/firebase_analytics.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; import 'package:flutter/foundation.dart'; import 'package:get/get.dart'; class FirebaseLogger extends GetxService { static FirebaseLogger get to => Get.find(); // ── Belső referenciák ───────────────────────────────────────────── late final FirebaseCrashlytics _crashlytics; late final FirebaseAnalytics _analytics; bool _isReady = false; // ── Lifecycle ───────────────────────────────────────────────────── @override Future onReady() async { super.onReady(); try { _crashlytics = FirebaseCrashlytics.instance; _analytics = FirebaseAnalytics.instance; // Crashlytics engedélyezése — release-ben mindig, debug-ban opcionális await _crashlytics.setCrashlyticsCollectionEnabled(!kDebugMode); // Eszközazonosító beállítása ha már elérhető _setDeviceInfo(); _isReady = true; _crashlytics.log('FirebaseLogger inicializálva'); } catch (e) { debugPrint('FirebaseLogger init hiba: $e'); } } // ── Publikus API — ugyanolyan mint AppLogger ────────────────────── /// Info szintű log — Crashlytics breadcrumb static void i(String tag, String message) { _breadcrumb('I', tag, message); } /// Figyelmeztetés — breadcrumb + Analytics esemény static void w(String tag, String message, {Object? error}) { _breadcrumb('W', tag, message); _logWarningEvent(tag, message, error: error); } /// Hiba — Crashlytics recordError + Analytics esemény static void e( String tag, String message, { Object? error, StackTrace? stack, bool fatal = false, }) { _breadcrumb('E', tag, message); if (error != null) { try { FirebaseLogger.to._crashlytics.recordError( error, stack, reason: '[$tag] $message', fatal: fatal, printDetails: kDebugMode, information: ['tag: $tag', 'message: $message'], ); } catch (_) {} } _logErrorEvent(tag, message, error: error); } /// Szeparátor — jól látható elválasztó a Crashlytics logban static void separator(String label) { _breadcrumb('─', '─────', '─── $label ───────────────────────'); } /// Egyedi Analytics esemény — tetszőleges adatokkal static void event( String name, [ Map? parameters, ]) { try { FirebaseLogger.to._analytics.logEvent( name: _sanitizeEventName(name), parameters: parameters, ); } catch (_) {} } /// Egyedi Crashlytics attribútum beállítása static void setKey(String key, dynamic value) { try { FirebaseLogger.to._crashlytics.setCustomKey(key, value); } catch (_) {} } // ── Eszközinfo beállítása ───────────────────────────────────────── void _setDeviceInfo() { try { // DeviceIdentityService ha már elérhető if (Get.isRegistered()) { final deviceService = Get.find(tag: 'DeviceIdentityService'); _crashlytics.setUserIdentifier(deviceService.deviceId ?? ''); } } catch (_) { // DeviceIdentityService még nem regisztrált — nem baj } } /// Crashlytics azonosító frissítése ha a DeviceIdentityService betöltött static void setDeviceIdentifier(String deviceId, String label) { try { FirebaseLogger.to._crashlytics.setUserIdentifier(deviceId); FirebaseLogger.to._crashlytics.setCustomKey('device_label', label); } catch (_) {} } // ── Belső segédek ───────────────────────────────────────────────── static void _breadcrumb(String level, String tag, String message) { try { final line = '$level [$tag] $message'; FirebaseLogger.to._crashlytics.log(line); } catch (_) {} } static void _logWarningEvent( String tag, String message, { Object? error, }) { try { FirebaseLogger.to._analytics.logEvent( name: 'app_warning', parameters: { 'tag': _trim(tag, 40), 'message': _trim(message, 100), if (error != null) 'error': _trim(error.toString(), 100), }, ); } catch (_) {} } static void _logErrorEvent( String tag, String message, { Object? error, }) { try { FirebaseLogger.to._analytics.logEvent( name: 'app_error', parameters: { 'tag': _trim(tag, 40), 'message': _trim(message, 100), if (error != null) 'error': _trim(error.toString(), 100), }, ); } catch (_) {} } /// Analytics eseménynevek csak betűt, számot és _ -t tartalmazhatnak static String _sanitizeEventName(String name) => name.replaceAll(RegExp(r'[^a-zA-Z0-9_]'), '_').substring( 0, name.length.clamp(0, 40), ); /// Analytics paraméter érték max 100 karakter static String _trim(String s, int max) => s.length > max ? s.substring(0, max) : s; }