AppLogger bővítése, mentés Supabase-be is
This commit is contained in:
@@ -54,6 +54,8 @@ Future<void> main() async {
|
|||||||
FirebaseCrashlytics.instance.recordError(error, stack, fatal: false);
|
FirebaseCrashlytics.instance.recordError(error, stack, fatal: false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
AppLogger.e('PlatformDispatcher', 'Kezeletlen kivétel',
|
||||||
|
error: error, stack: stack);
|
||||||
FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
|
FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
// Log fájl helye: /sdcard/Android/data/hu.app_dev.terepi_seged/files/logs/
|
// Log fájl helye: /sdcard/Android/data/hu.app_dev.terepi_seged/files/logs/
|
||||||
// Elérhető: Android Studio Device Explorer, adb pull, vagy fájlkezelő app
|
// Elérhető: Android Studio Device Explorer, adb pull, vagy fájlkezelő app
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@@ -16,6 +17,8 @@ import 'package:intl/intl.dart';
|
|||||||
import 'package:path/path.dart' as p;
|
import 'package:path/path.dart' as p;
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:share_plus/share_plus.dart';
|
import 'package:share_plus/share_plus.dart';
|
||||||
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||||
|
import 'package:terepi_seged/services/device_identity_service.dart';
|
||||||
|
|
||||||
enum _Level { info, warning, error }
|
enum _Level { info, warning, error }
|
||||||
|
|
||||||
@@ -73,17 +76,23 @@ class AppLogger extends GetxService {
|
|||||||
// ── Publikus API ──────────────────────────────────────────────────
|
// ── Publikus API ──────────────────────────────────────────────────
|
||||||
|
|
||||||
/// Info szintű log
|
/// Info szintű log
|
||||||
static void i(String tag, String message) =>
|
static void i(String tag, String message) {
|
||||||
_write(_Level.info, tag, message);
|
_write(_Level.info, tag, message);
|
||||||
|
_remoteLog("INFO", tag, message, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
/// Figyelmeztetés
|
/// Figyelmeztetés
|
||||||
static void w(String tag, String message, {Object? error}) =>
|
static void w(String tag, String message, {Object? error}) {
|
||||||
_write(_Level.warning, tag, message, error: error);
|
_write(_Level.warning, tag, message, error: error);
|
||||||
|
_remoteLog("WARN", tag, message, error, null);
|
||||||
|
}
|
||||||
|
|
||||||
/// Hiba
|
/// Hiba
|
||||||
static void e(String tag, String message,
|
static void e(String tag, String message,
|
||||||
{Object? error, StackTrace? stack}) =>
|
{Object? error, StackTrace? stack}) {
|
||||||
_write(_Level.error, tag, message, error: error, stack: stack);
|
_write(_Level.error, tag, message, error: error, stack: stack);
|
||||||
|
_remoteLog("ERROR", tag, message, error, stack);
|
||||||
|
}
|
||||||
|
|
||||||
/// Szeparátor — jól látható elválasztó a logban
|
/// Szeparátor — jól látható elválasztó a logban
|
||||||
static void separator(String label) {
|
static void separator(String label) {
|
||||||
@@ -236,4 +245,101 @@ class AppLogger extends GetxService {
|
|||||||
await files.removeAt(0).delete();
|
await files.removeAt(0).delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Távoli (Supabase) hiba-napló ──────────────────────────────────
|
||||||
|
|
||||||
|
static final Map<String, DateTime> _remoteLogDedup = {};
|
||||||
|
static const _remoteLogDedupWindow = Duration(seconds: 60);
|
||||||
|
|
||||||
|
static void _remoteLog(
|
||||||
|
String type, String tag, String message, Object? error, StackTrace? stack,
|
||||||
|
[String? info, Map<String, dynamic>? params]) {
|
||||||
|
final key = '$tag|$message';
|
||||||
|
final last = _remoteLogDedup[key];
|
||||||
|
final now = DateTime.now();
|
||||||
|
if (last != null && now.difference(last) < _remoteLogDedupWindow) {
|
||||||
|
return; // ugyanaz a hiba nemrég már felment — ne floodoljuk
|
||||||
|
}
|
||||||
|
_remoteLogDedup[key] = now;
|
||||||
|
|
||||||
|
unawaited(() async {
|
||||||
|
try {
|
||||||
|
String? deviceId;
|
||||||
|
String? appVersion;
|
||||||
|
String? model;
|
||||||
|
String? appInstanceId;
|
||||||
|
String? platform;
|
||||||
|
if (Get.isRegistered<DeviceIdentityService>()) {
|
||||||
|
final d = DeviceIdentityService.to;
|
||||||
|
deviceId = d.isReady ? d.deviceId : null;
|
||||||
|
appVersion = d.isReady ? d.appInfo : null;
|
||||||
|
model = d.isReady ? d.model : null;
|
||||||
|
appInstanceId = d.isReady ? d.appInstanceId : null;
|
||||||
|
platform = d.isReady ? d.info.platform : null;
|
||||||
|
}
|
||||||
|
final userId = Supabase.instance.client.auth.currentUser?.id;
|
||||||
|
|
||||||
|
await Supabase.instance.client.from('terepi_seged_logs').insert({
|
||||||
|
'tag': tag,
|
||||||
|
'message': message,
|
||||||
|
'error_text': error?.toString(),
|
||||||
|
'stack_text': stack != null
|
||||||
|
? stack.toString().split('\n').take(8).join('\n')
|
||||||
|
: null,
|
||||||
|
'app_version': appVersion,
|
||||||
|
'device_id': deviceId,
|
||||||
|
'user_id': userId,
|
||||||
|
'app_id': appInstanceId,
|
||||||
|
'model': model,
|
||||||
|
'platform': platform,
|
||||||
|
'info': info,
|
||||||
|
'params': params
|
||||||
|
}).timeout(const Duration(seconds: 5));
|
||||||
|
} catch (_) {
|
||||||
|
// Szándékosan néma — a távoli naplózás hibája NEM okozhat
|
||||||
|
// újabb naplóbejegyzést (végtelen ciklus elkerülése).
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Egyszerű, "Firebase Analytics"-stílusú esemény-napló ──────────
|
||||||
|
// NEM a Firebase-be megy — ugyanabba a Supabase-be, mint a hiba-napló,
|
||||||
|
// hogy a hiba ÉS a használati esemény is egy helyen, azonnal
|
||||||
|
// lekérdezhető legyen (a valódi Firebase Analytics konzolja akár
|
||||||
|
// 24 órás késleltetéssel jelenít meg adatokat).
|
||||||
|
|
||||||
|
static void event(String name, [String? info, Map<String, dynamic>? params]) {
|
||||||
|
unawaited(() async {
|
||||||
|
try {
|
||||||
|
String? deviceId;
|
||||||
|
String? appVersion;
|
||||||
|
String? model;
|
||||||
|
String? appInstanceId;
|
||||||
|
String? platform;
|
||||||
|
if (Get.isRegistered<DeviceIdentityService>()) {
|
||||||
|
final d = DeviceIdentityService.to;
|
||||||
|
deviceId = d.isReady ? d.deviceId : null;
|
||||||
|
appVersion = d.isReady ? d.appInfo : null;
|
||||||
|
model = d.isReady ? d.model : null;
|
||||||
|
appInstanceId = d.isReady ? d.appInstanceId : null;
|
||||||
|
platform = d.isReady ? d.info.platform : null;
|
||||||
|
}
|
||||||
|
final userId = Supabase.instance.client.auth.currentUser?.id;
|
||||||
|
|
||||||
|
await Supabase.instance.client.from('terepi_seged_events').insert({
|
||||||
|
'event_name': name,
|
||||||
|
'params': params,
|
||||||
|
'app_version': appVersion,
|
||||||
|
'device_id': deviceId,
|
||||||
|
'user_id': userId,
|
||||||
|
'app_id': appInstanceId,
|
||||||
|
'model': model,
|
||||||
|
'platform': platform,
|
||||||
|
'info': info
|
||||||
|
}).timeout(const Duration(seconds: 5));
|
||||||
|
} catch (_) {
|
||||||
|
// Néma — az esemény-naplózás hibája nem árthat a funkciónak.
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user