📝 Log Viewer

Log Viewer / 日志查看器

Overview / 概述

The Log Viewer automatically captures logs from multiple sources with zero configuration.

日志查看器自动从多个来源捕获日志,无需配置。

Log Sources / 日志来源

SourceCapture Method
print()Zone specification override / Zone 规范覆盖
debugPrint()debugPrint override / debugPrint 覆盖
Flutter errorsFlutterError.onError hook / 接管 FlutterError.onError
Unhandled exceptionsrunZonedGuarded / runZonedGuarded 捕获
Third-party librariesVia print() capture / 通过 print() 捕获

Since v1.9.0, Flutter framework errors and unhandled exceptions are also aggregated & deduplicated in the dedicated Errors tab (keyed by type + stack signature) — while this Log Viewer keeps showing them as error-level lines in the chronological stream. Use Errors for “is this crash repeating?”; use Log Viewer for the raw timeline.

自 v1.9.0 起,Flutter 框架异常与未捕获异常会同时进入独立的 Errors 标签页去重聚合(按类型 + 堆栈签名归并);本 Log Viewer 仍会在原始时间流中把它们显示为错误级日志。回答”该崩溃是否反复出现”请用 Errors;查看原始时间线请用 Log Viewer。

Log Levels / 日志级别

LevelAbbreviationColorDescription
VerboseVGrayDetailed information / 详细信息
DebugDBlueDebug information / 调试信息
InfoIGreenGeneral information / 一般信息
WarningWOrangeWarning messages / 警告信息
ErrorERedError messages / 错误信息

Third-party library logs are categorized as Info level.

第三方日志库的日志统一归类为 Info 级别。

UI Features / UI 功能

Filter Bar / 过滤栏

  • All: Show all logs / 使用 All 显示所有日志
  • V / D / I / W / E: Filter by level / 按级别过滤
  • Tag dropdown: Filter by any captured tag / 按任意已捕获标签过滤
  • Single-select mode / 单选模式

Toolbar / 工具栏

  • Auto-scroll toggle (default on): Jump to the newest log as new entries arrive; pause to keep history still for inspection / 自动滚动开关(默认开启):新日志到达时自动跳到最新;暂停可稳定查看历史
  • Copy as JSON: Copy all currently filtered logs as JSON / 复制为 JSON:将当前过滤后的全部日志复制为 JSON
  • Share as Text: Share filtered logs as plain text / 分享为文本:将过滤后的日志以纯文本分享
  • Clear: Clear all logs / 清除:清空全部日志

Log List / 日志列表

  • Level badge with color / 带颜色的级别徽章
  • Timestamp display / 时间戳显示
  • Tag display (if available) / 标签显示(如有)
  • Error/warning rows have subtle background tint / 错误/警告行有淡色背景
  • Left border color indicates level / 左侧边框颜色表示级别
  • Tap a row to open the in-view detail page with full message and copy; use the back button to return / 点击行进入详情页(主视图内切换),可查看完整消息并复制,点返回按钮回到列表
  • Per-row copy button copies that single log as JSON / 行内复制按钮将该条日志以 JSON 复制

Search / 搜索

  • Fuzzy search by message content or tag / 按消息内容或标签模糊搜索
  • Toggle regex mode (. * button) to search with RegExp (case-insensitive); invalid patterns degrade gracefully instead of crashing / 点击 正则模式(. * 按钮)使用 RegExp 搜索(不区分大小写);非法图案优雅降级,不会崩溃
  • Combined with level and tag filters / 可与级别、标签过滤组合使用

Manual Logging / 手动记录日志

Quick shorthand (recommended) / 简化写法(推荐) — available since v1.1.2 / v1.1.2 起可用:

InspectorLog.v('Verbose message / 详细消息');
InspectorLog.d('Debug message / 调试消息');
InspectorLog.i('Info message / 信息消息');
InspectorLog.w('Warning message / 警告消息');
InspectorLog.e('Error message / 错误消息');
 
// With tag / 带标签
InspectorLog.i('User logged in', tag: 'Auth');

Full form / 完整写法:

InspectorLogInterceptor.instance.verbose('Verbose message / 详细消息');
InspectorLogInterceptor.instance.debug('Debug message / 调试消息');
InspectorLogInterceptor.instance.info('Info message / 信息消息');
InspectorLogInterceptor.instance.warning('Warning message / 警告消息');
InspectorLogInterceptor.instance.error('Error message / 错误消息');
 
// With tag / 带标签
InspectorLogInterceptor.instance.info('User logged in', tag: 'Auth');

InspectorLog is a static wrapper around InspectorLogInterceptor.instance for shorter log calls.

InspectorLog 是 InspectorLogInterceptor.instance 的静态包装,用于更简短的日志调用。

Third-Party Library Integration / 第三方日志库集成

Auto-Capture (Inbound) / 自动捕获(入站)

No configuration needed. Any library using print() or debugPrint() is automatically captured.

无需配置。任何使用 print() 或 debugPrint() 的库都会被自动捕获。

Bidirectional Sync (Optional) / 双向同步(可选)

To forward inspector logs to your third-party logger:

将检查器日志转发到第三方日志库:

import 'package:logger/logger.dart';
 
final logger = Logger();
 
InspectorLogInterceptor.instance.onLogCaptured = (entry) {
  logger.log(
    _mapLogLevel(entry.level),
    '${entry.tag != null ? '[${entry.tag}] ' : ''}${entry.message}',
  );
};

Note: Do NOT call logging methods inside onLogCaptured, as this will cause infinite recursion. 注意:不要在 onLogCaptured 内部调用日志方法,否则会导致无限递归。

Starting the Log Interceptor / 启动日志拦截器

If using runAppWithInspector(), the log interceptor starts automatically. Otherwise:

如果使用 runAppWithInspector(),日志拦截器会自动启动。否则:

InspectorLogInterceptor.instance.start();