import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:logging/logging.dart' as std_log; import 'package:logger/logger.dart' as pretty_log; import 'auth_proxy_service.dart'; import 'log_policy.dart'; import 'runtime_env.dart'; /// Global Logger Service for Baron SSO Frontend class LoggerService { static final LoggerService _instance = LoggerService._internal(); factory LoggerService() => _instance; late final pretty_log.Logger _prettyLogger; late final String _appEnv; late final String _productionDebugFlag; LoggerService._internal() { _appEnv = envOrDefault('APP_ENV', 'dev'); _productionDebugFlag = envOrDefault( 'CLIENT_LOG_DEBUG', envOrDefault('USERFRONT_DEBUG_LOG', ''), ); final debugEnabled = LogPolicy.debugEnabled( appEnv: _appEnv, productionDebugFlag: _productionDebugFlag, ); // 1. Initialize Pretty Logger for Dev _prettyLogger = pretty_log.Logger( printer: pretty_log.PrettyPrinter( methodCount: 0, errorMethodCount: 8, lineLength: 120, colors: true, printEmojis: true, dateTimeFormat: pretty_log.DateTimeFormat.onlyTimeAndSinceStart, ), ); // 2. Configure Standard Logger (logging package) std_log.Logger.root.level = debugEnabled ? std_log.Level.ALL : std_log.Level.WARNING; std_log.Logger.root.onRecord.listen((record) { if (kReleaseMode) { // [Production] Log as JSON _logJson(record); } else { // [Development] Log using Pretty Printer _logPretty(record); } }); } /// Initialize the logger. Call this in main.dart static void init() { // Accessing the instance triggers the constructor LoggerService(); std_log.Logger('BaronSSO').info('Logger initialized'); } void _logPretty(std_log.LogRecord record) { if (record.level >= std_log.Level.SEVERE) { _prettyLogger.e( record.message, error: record.error, stackTrace: record.stackTrace, ); } else if (record.level >= std_log.Level.WARNING) { _prettyLogger.w(record.message); } else if (record.level >= std_log.Level.INFO) { _prettyLogger.i(record.message); } else { _prettyLogger.d(record.message); } } void _logJson(std_log.LogRecord record) { final sanitizedMessage = LogPolicy.sanitizeMessage(record.message); final logData = { 'time': record.time.toUtc().toIso8601String(), // Use UTC for consistency 'level': record.level.name, 'msg': sanitizedMessage, 'svc': 'baron-userfront', if (record.error != null) 'error': record.error.toString(), if (record.stackTrace != null) 'stack': record.stackTrace.toString(), }; // 1. Print to Browser Console (F12) debugPrint(jsonEncode(logData)); // 2. Relay to Backend (Docker Terminal) if (LogPolicy.shouldRelayClientLog( level: record.level.name, appEnv: _appEnv, productionDebugFlag: _productionDebugFlag, )) { AuthProxyService.sendLog( record.level.name, sanitizedMessage, data: { 'client_time': record.time.toUtc().toIso8601String(), 'logger': record.loggerName, if (record.error != null) 'error': record.error.toString(), }, ); } } }