SOUI 日志系统使用指南¶
Warning
The current page still doesn't have a translation for this language.
You can read it through google translate.
SOUI 框架提供了一套完整的日志系统,用于帮助开发者调试和监控应用程序运行状态。新版本的日志系统借鉴了 webrtc 的流式输出日志方法,使日志输出格式更加简洁易用。
日志系统架构¶
SOUI 的日志系统由两个核心部分组成:
- 日志输出宏:提供便捷的日志记录接口
- 日志打印模块:负责将日志输出到文件或调试窗口
日志打印模块基于 log4z 代码进行修改,以适配 SOUI 的接口需求。
日志输出方式¶
SOUI 支持两种日志输出方式:
- 文件输出:配置日志打印模块后,日志可直接输出到 log 文件
- 调试窗口输出:不配置打印模块时,默认使用 OutputDebugString 输出到调试窗口
日志打印模块配置¶
要在 SOUI 中使用日志打印模块,需要进行如下配置:
if (pComMgr->CreateLog4z((IObjRef**)&pLogMgr) && pLogMgr)
{
// 取消注释下一行可禁用日志管理器输出调试字符串
// pLogMgr->setLoggerDisplay(LOG4Z_MAIN_LOGGER_ID, false);
// 取消注释下一行可记录信息级别日志
// pLogMgr->setLoggerLevel(LOG4Z_MAIN_LOGGER_ID, LOG_LEVEL_INFO);
pLogMgr->start();
}
// 定义一个唯一的 SApplication 对象,SApplication 管理整个应用程序的资源
SApplication* theApp = new SApplication2(pRenderFactory, hInstance);
// 将日志模块交给 SApp 管理
theApp->SetLogManager(pLogMgr);
日志输出宏详解¶
SOUI 提供了丰富的日志输出宏,满足不同场景的使用需求:
流式输出宏¶
基于 kLogTag 的流式输出¶
// 流式输出日志,当 kLogTag 有效时使用,否则编译失败
// kLogTag 可以是当前定义的宏,也可以是当前对象的成员变量
#define SLOGD() SLOG(kLogTag,SOUI::Log::LOG_DEBUG,0)
#define SLOGI() SLOG(kLogTag,SOUI::Log::LOG_INFO,0)
#define SLOGW() SLOG(kLogTag,SOUI::Log::LOG_WARN,0)
#define SLOGE() SLOG(kLogTag,SOUI::Log::LOG_ERROR,0)
#define SLOGF() SLOG(kLogTag,SOUI::Log::LOG_FATAL,0)
手动指定 Tag 的流式输出¶
// 流式输出日志,每条日志手动指定 tag
#define SLOGD2(tag) SLOG(tag,SOUI::Log::LOG_DEBUG,0)
#define SLOGI2(tag) SLOG(tag,SOUI::Log::LOG_INFO,0)
#define SLOGW2(tag) SLOG(tag,SOUI::Log::LOG_WARN,0)
#define SLOGE2(tag) SLOG(tag,SOUI::Log::LOG_ERROR,0)
#define SLOGF2(tag) SLOG(tag,SOUI::Log::LOG_FATAL,0)
格式化输出宏¶
基于 kLogTag 的格式化输出¶
// 格式化输出日志,当 kLogTag 有效时使用
#define SLOGFMTD(logformat, ...) SLOG_FMT(kLogTag,SOUI::Log::LOG_DEBUG,0,logformat,##__VA_ARGS__)
#define SLOGFMTI(logformat, ...) SLOG_FMT(kLogTag,SOUI::Log::LOG_INFO,0,logformat,##__VA_ARGS__)
#define SLOGFMTW(logformat, ...) SLOG_FMT(kLogTag,SOUI::Log::LOG_WARN,0,logformat,##__VA_ARGS__)
#define SLOGFMTE(logformat, ...) SLOG_FMT(kLogTag,SOUI::Log::LOG_ERROR,0,logformat,##__VA_ARGS__)
#define SLOGFMTF(logformat, ...) SLOG_FMT(kLogTag,SOUI::Log::LOG_FATAL,0,logformat,##__VA_ARGS__)
手动指定 Tag 的格式化输出¶
// 格式化输出日志,每条日志手动指定 tag
#define SLOGFMTD2(tag,logformat, ...) SLOG_FMT(tag,SOUI::Log::LOG_DEBUG,0,logformat,##__VA_ARGS__)
#define SLOGFMTI2(tag,logformat, ...) SLOG_FMT(tag,SOUI::Log::LOG_INFO,0,logformat,##__VA_ARGS__)
#define SLOGFMTW2(tag,logformat, ...) SLOG_FMT(tag,SOUI::Log::LOG_WARN,0,logformat,##__VA_ARGS__)
#define SLOGFMTE2(tag,logformat, ...) SLOG_FMT(tag,SOUI::Log::LOG_ERROR,0,logformat,##__VA_ARGS__)
#define SLOGFMTF2(tag,logformat, ...) SLOG_FMT(tag,SOUI::Log::LOG_FATAL,0,logformat,##__VA_ARGS__)
SOUI 内部使用宏¶
// SOUI4 内部使用的日志输出,自动将 TAG 定义为 soui4
#define kSoui4Tag "soui4"
#define SSLOGD() SLOG(kSoui4Tag,SOUI::Log::LOG_DEBUG,0)
#define SSLOGI() SLOG(kSoui4Tag,SOUI::Log::LOG_INFO,0)
#define SSLOGW() SLOG(kSoui4Tag,SOUI::Log::LOG_WARN,0)
#define SSLOGE() SLOG(kSoui4Tag,SOUI::Log::LOG_ERROR,0)
#define SSLOGF() SLOG(kSoui4Tag,SOUI::Log::LOG_FATAL,0)
#define SSLOGFMTD(logformat, ...) SLOG_FMT(kSoui4Tag,SOUI::Log::LOG_DEBUG,0,logformat,##__VA_ARGS__)
#define SSLOGFMTI(logformat, ...) SLOG_FMT(kSoui4Tag,SOUI::Log::LOG_INFO,0,logformat,##__VA_ARGS__)
#define SSLOGFMTW(logformat, ...) SLOG_FMT(kSoui4Tag,SOUI::Log::LOG_WARN,0,logformat,##__VA_ARGS__)
#define SSLOGFMTE(logformat, ...) SLOG_FMT(kSoui4Tag,SOUI::Log::LOG_ERROR,0,logformat,##__VA_ARGS__)
#define SSLOGFMTF(logformat, ...) SLOG_FMT(kSoui4Tag,SOUI::Log::LOG_FATAL,0,logformat,##__VA_ARGS__)
使用示例¶
流式日志输出¶
使用 SLOGx 系列宏需要在当前代码中定义 kLogTag 宏或可访问变量:
#define kLogTag "demo"
// 使用流式输出
SLOGI() << "test=" << 200;
SLOGW() << "warning message: " << "something went wrong";
SLOGE() << "error occurred: " << GetLastError();
如果希望使用不同的 tag,可以使用 SLOGx2 系列宏:
SLOGI2("tag1") << "test=" << 200;
SLOGI2("tag2") << "another test=" << 300;
SLOGW2("network") << "connection timeout";
格式化日志输出¶
SOUI 还提供了格式化输出宏,使用方式类似于 printf:
#define kLogTag "demo"
// 格式化输出(基于 kLogTag)
SLOGFMTE(L"log output using unicode format,str=%s, tick=%u", L"中文", GetTickCount());
SLOGFMTI("log output using ansi format,str=%s, tick=%u", "test", GetTickCount());
// 格式化输出(手动指定 tag)
SLOGFMTE2("newtag", L"log output using unicode format,str=%s, tick=%u", L"中文", GetTickCount());
注意:在格式化输出宏中,会根据 format 参数自动选择以宽字符还是 Ansi 字符串来格式化输出。如果 format 是宽字符,则后续的 %s 对应的字符串也必须是宽字符串。
SOUI 内部日志¶
SSLOGx 系列宏是 SOUI 内部使用的宏,与前面几组宏的唯一区别在于自动将 tag 固定为 "soui4":
SSLOGI() << "internal SOUI message";
SSLOGFMTE("error in SOUI module: %s", "module failed to initialize");
最佳实践¶
- 合理使用日志级别:
- DEBUG:调试信息,用于开发阶段
- INFO:一般信息,用于记录程序运行状态
- WARN:警告信息,程序可以继续运行
- ERROR:错误信息,功能受到影响
-
FATAL:致命错误,程序无法继续运行
-
统一 Tag 命名:
- 在每个模块的开始定义 kLogTag
-
使用有意义的 tag 名称,便于日志分类和过滤
-
性能考虑:
- 避免在高频调用的代码中输出 DEBUG 级别日志
-
生产环境中可适当调整日志级别
-
字符编码注意:
- 宽字符和 Ansi 字符串要匹配使用
- 在格式化输出中特别注意字符串类型一致性
通过合理使用 SOUI 的日志系统,可以大大提高应用程序的可调试性和可维护性。