refactor: remove CrashReporter and related logging components

- Removed CrashReporter interface and its implementation, SentryCrashReporter.
- Deleted log buffering functionality and associated LogBuffer class.
- Updated LoggerAppLogger to eliminate dependencies on removed components.
- Simplified logging structure to focus on AppLogger and sensitive data scrubbing.
- Adjusted AppEnv to remove Sentry-related configurations.
- Refactored tests to align with the new logging architecture.
This commit is contained in:
Guangfei.Zhao
2026-09-03 11:39:04 +08:00
parent d786fc31ff
commit 782fba80bc
39 changed files with 192 additions and 1152 deletions
+15 -23
View File
@@ -22,41 +22,36 @@ enum AppFlavor {
/// **所有环境差异都收敛在这一个类里**,业务代码里不允许出现
/// `if (kDebugMode)` 或 `if (host.contains('uat'))` 这类判断。
///
/// 值来自 `--dart-define-from-file=env/{flavor}.json`(见 08)。构建时不传这个
/// 参数会得到空的 baseUrl,[fromDartDefine] 会直接抛错而不是让 App 带着空配置跑起来——
/// 这种错误必须在启动瞬间暴露,而不是等第一个网络请求 404。
/// 值来自随 App 打包的 `env/{flavor}.json`。配置无效时会在启动瞬间暴露,
/// 而不是等第一个网络请求 404。
class AppEnv {
const AppEnv({
required this.flavor,
required this.apiBaseUrl,
required this.enableLog,
required this.sentryDsn,
required this.h5AllowedHosts,
});
/// 从 `--dart-define-from-file` 注入的值构造。
///
/// [flavor] 由各自的入口文件(main_dev.dart / main_uat.dart / main_prod.dart)
/// 硬编码传入,而不是从 dart-define 读——这样"用 dev 的入口配了 prod 的 json"
/// 这种事故在代码里看得见。
factory AppEnv.fromDartDefine({required String flavor}) {
const apiBaseUrl = String.fromEnvironment('API_BASE_URL');
const enableLog = bool.fromEnvironment('ENABLE_LOG');
const sentryDsn = String.fromEnvironment('SENTRY_DSN');
const h5AllowedHosts = String.fromEnvironment('H5_ALLOWED_HOSTS');
/// 从已解析的环境 JSON 构造,并在启动期验证所有必填字段。
factory AppEnv.fromConfig({required String flavor, required Map<String, Object?> values}) {
final Object? apiBaseUrl = values['API_BASE_URL'];
final Object? enableLog = values['ENABLE_LOG'];
final Object? h5AllowedHosts = values['H5_ALLOWED_HOSTS'];
if (apiBaseUrl.isEmpty) {
throw StateError(
'API_BASE_URL 为空。启动时必须带上 --dart-define-from-file=env/$flavor.json,'
'见 README「怎么跑起来」。',
);
if (apiBaseUrl is! String || apiBaseUrl.trim().isEmpty) {
throw StateError('环境 $flavor 的 API_BASE_URL 必须是非空字符串。');
}
if (enableLog is! bool) {
throw StateError('环境 $flavor 的 ENABLE_LOG 必须是布尔值。');
}
if (h5AllowedHosts is! String) {
throw StateError('环境 $flavor 的 H5_ALLOWED_HOSTS 必须是字符串。');
}
return AppEnv(
flavor: AppFlavor.parse(flavor),
apiBaseUrl: apiBaseUrl,
enableLog: enableLog,
sentryDsn: sentryDsn,
h5AllowedHosts: _parseHosts(h5AllowedHosts),
);
}
@@ -75,9 +70,6 @@ class AppEnv {
/// 是否输出网络日志和 debug 级日志。prod 必须为 false(见 13)。
final bool enableLog;
/// 为空表示不启用 Sentry(dev 默认不上报,避免把开发期噪音混进线上数据)。
final String sentryDsn;
/// H5 域名白名单。WebView 只允许加载这些域名及其子域,见 10。
final Set<String> h5AllowedHosts;
@@ -44,12 +44,48 @@ void main() {
flavor: AppFlavor.dev,
apiBaseUrl: 'https://api-dev.conti.com',
enableLog: true,
sentryDsn: '',
h5AllowedHosts: <String>{'f6.conti.com'},
);
expect(env.isProd, isFalse);
expect(env.flavorSuffixVisible, isTrue);
expect(env.h5AllowedHosts, contains('f6.conti.com'));
});
test('从内置环境配置读取字段并规范化 H5 域名', () {
final AppEnv env = AppEnv.fromConfig(
flavor: 'uat',
values: <String, Object?>{
'API_BASE_URL': 'https://api-uat.conti.com',
'ENABLE_LOG': true,
'H5_ALLOWED_HOSTS': ' H5.Conti.com, shop.conti.com ',
},
);
expect(env.flavor, AppFlavor.uat);
expect(env.apiBaseUrl, 'https://api-uat.conti.com');
expect(env.enableLog, isTrue);
expect(env.h5AllowedHosts, <String>{'h5.conti.com', 'shop.conti.com'});
});
test('缺失或类型错误的内置配置在启动期失败', () {
expect(
() => AppEnv.fromConfig(
flavor: 'dev',
values: <String, Object?>{'API_BASE_URL': '', 'ENABLE_LOG': true, 'H5_ALLOWED_HOSTS': ''},
),
throwsStateError,
);
expect(
() => AppEnv.fromConfig(
flavor: 'dev',
values: <String, Object?>{
'API_BASE_URL': 'https://api-dev.conti.com',
'ENABLE_LOG': 'true',
'H5_ALLOWED_HOSTS': '',
},
),
throwsStateError,
);
});
});
}