skywood/lib/global/tool/sky_log.dart

147 lines
3.3 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)];
}