147 lines
3.3 KiB
Dart
147 lines
3.3 KiB
Dart
import 'dart:convert';
|
||
import 'dart:developer';
|
||
|
||
import 'package:flutter/foundation.dart';
|
||
import 'package:talker_flutter/talker_flutter.dart';
|
||
|
||
class SkyLog {
|
||
SkyLog._();
|
||
|
||
static final SkyLog _instance = SkyLog._();
|
||
|
||
static SkyLog get instance => _instance;
|
||
|
||
final Talker _talker = TalkerFlutter.init();
|
||
|
||
factory SkyLog() => _instance;
|
||
|
||
Talker get tLog => _talker;
|
||
|
||
/// DevTools / 控制台里可按名称过滤。
|
||
static const String logName = 'SkyLog';
|
||
|
||
Future<void> initLogger() async {
|
||
/// app 信息
|
||
}
|
||
|
||
/// 仅 [kDebugMode] 输出;内容经安全格式化,不会因无法 JSON 编码而中断业务逻辑。
|
||
static void print(
|
||
Object? message, {
|
||
String? tag,
|
||
String name = logName,
|
||
}) {
|
||
if (!kDebugMode) return;
|
||
try {
|
||
final text = _stringify(message);
|
||
final line = tag != null ? '[debug-tag: $tag] ===== $text' : text;
|
||
log(line, name: name);
|
||
} catch (e, st) {
|
||
log(
|
||
'[SkyLog.print failed] $e',
|
||
name: name,
|
||
error: e,
|
||
stackTrace: st,
|
||
);
|
||
}
|
||
}
|
||
|
||
/// 尽量输出缩进 JSON;无法编码时退回 [toString],不向外抛错。
|
||
static String _stringify(Object? value) {
|
||
if (value == null) return 'null';
|
||
if (value is String) return value;
|
||
if (value is num || value is bool) return value.toString();
|
||
|
||
const encoder = JsonEncoder.withIndent(' ');
|
||
|
||
if (value is Map) {
|
||
try {
|
||
return encoder.convert(value);
|
||
} catch (_) {
|
||
return value.toString();
|
||
}
|
||
}
|
||
if (value is List) {
|
||
try {
|
||
return encoder.convert(value);
|
||
} catch (_) {
|
||
return value.toString();
|
||
}
|
||
}
|
||
if (value is Iterable) {
|
||
try {
|
||
return encoder.convert(value.toList());
|
||
} catch (_) {
|
||
return value.toString();
|
||
}
|
||
}
|
||
|
||
try {
|
||
return encoder.convert(value);
|
||
} catch (_) {
|
||
try {
|
||
return '${value.runtimeType}: $value';
|
||
} catch (_) {
|
||
return '<unprintable ${value.runtimeType}>';
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 错误日志走 Talker;若 Talker 抛错,在 Debug 下用 [log] 兜底,仍不向外抛。
|
||
static void error(
|
||
Object? message, {
|
||
String? tag,
|
||
StackTrace? stackTrace,
|
||
}) {
|
||
final text = message == null ? 'null' : '$message';
|
||
try {
|
||
_instance._talker.logCustom(
|
||
CustomLog(
|
||
text,
|
||
settings: _instance._talker.settings,
|
||
tag: tag,
|
||
logLevel: LogLevel.error,
|
||
stackTrace: stackTrace,
|
||
),
|
||
);
|
||
} catch (e, st) {
|
||
if (kDebugMode) {
|
||
log(
|
||
'[SkyLog.error fallback] $text | $e',
|
||
name: logName,
|
||
error: e,
|
||
stackTrace: st,
|
||
);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
class CustomLog extends TalkerLog {
|
||
final String? tag;
|
||
final TalkerSettings settings;
|
||
final LogLevel? _logLevel;
|
||
final StackTrace? _stackTrace;
|
||
|
||
CustomLog(
|
||
super.message, {
|
||
this.tag,
|
||
required this.settings,
|
||
LogLevel logLevel = LogLevel.debug,
|
||
StackTrace? stackTrace,
|
||
}) : _logLevel = logLevel,
|
||
_stackTrace = stackTrace;
|
||
|
||
@override
|
||
String? get key => tag;
|
||
|
||
@override
|
||
LogLevel? get logLevel => _logLevel;
|
||
|
||
@override
|
||
StackTrace? get stackTrace => _stackTrace;
|
||
|
||
@override
|
||
AnsiPen? get pen =>
|
||
settings.colors[TalkerKey.fromLogLevel(logLevel ?? LogLevel.info)];
|
||
}
|