Debug Configuration API
命名空间:
mc::app头文件:#include <mc/app/debug.h>源文件:libraries/mcapp/src/micro_component/debug.cpp
目录
概述
mc/app/debug.h 中的七个函数均通过 MC_API 从 mcapp 共享库导出,包括本地持久化入口;外部消费者无需链接库内部对象。
mc::app::debug 模块提供 MicroComponent 日志配置的持久化功能,支持本地和远程两种持久化方式:
- 本地持久化:maca 和 persistence 服务使用本地 SQLite 数据库
- 远程持久化:其他服务通过 DBus 调用 persistence 服务
该模块在 MCDBUS_USE_OLD_SHM 模式下可用。
核心能力包括:
- 服务识别: 自动判断服务应使用本地还是远程持久化
- 应用名提取: 从完整服务名中提取应用名
- 配置持久化: 将调试配置(日志级别、输出类型、有效时长)保存到数据库
- 配置恢复: 从数据库加载调试配置,支持服务重启后恢复状态
主要特性
| 特性 | 说明 |
|---|---|
| 自动选择持久化方式 | 本地服务用 SQLite,其他服务用 DBus |
| 本地持久化路径 | 根据服务类型选择: - mini_system_app: /data/trust/persistence.local/{app_name}.db- 其他: /data/opt/bmc/persistence.local/{app_name}.db |
| 远程持久化表名 | _t_mc_properties_{app_name}(通过 DBus) |
| 服务识别 | 通过 is_local_persist_service() 判断服务类型 |
| 应用名提取 | extract_app_name() 从服务名提取应用名 |
| 异常安全 | 所有数据库操作都有 try-catch 保护 |
| 线程安全 | 配合 micro_component_object 的互斥锁使用 |
API 参考
is_local_persist_service
判断服务是否使用本地持久化存储。
bool is_local_persist_service(mc::string_view service_name);
参数:
service_name: 服务名(如bmc.kepler.maca)
返回值:
true: 使用本地 SQLite 存储(maca 或 persistence 服务)false: 使用远程持久化存储
说明:
- 该函数提取服务名的最后一部分,转为小写后与
maca或persistence比较 - 使用精确匹配,避免子串误判
extract_app_name
从服务名中提取应用名。
mc::string extract_app_name(mc::string_view service_name);
参数:
service_name: 服务名(如bmc.kepler.maca)
返回值:
- 应用名(如
maca)
save_debug_config
保存调试配置(自动选择持久化方式)。
void save_debug_config(mc::engine::service* svc,
mc::string_view level,
mc::string_view type,
uint8_t duration_hours);
参数:
svc: 服务对象(用于获取 DBus 连接和判断持久化方式)level: 日志级别(all,trace,debug,info,notice,warn,error,fatal,off)type: 日志输出类型(如file,socket等)duration_hours: 剩余有效时长(半小时数),0 表示永久
持久化方式:
- 本地持久化(maca/persistence):保存到本地 SQLite 数据库
- 远程持久化(其他服务):通过 DBus 调用 persistence 服务的
Save方法
远程持久化参数:
- 表名:
_t_mc_properties_{app_name} - 主键:
Id=1(固定值) - persist_type:
protect_power_off
load_debug_config
从数据库加载调试配置(自动选择持久化方式)。
bool load_debug_config(mc::engine::service* svc,
mc::string& level,
mc::string& type,
uint8_t& duration_hours);
参数:
svc: 服务对象level: [out] 日志级别type: [out] 日志输出类型duration_hours: [out] 剩余有效时长(半小时数)
返回值:
true: 加载成功false: 加载失败(数据库文件不存在、表不存在、无记录等)
持久化方式:
- 本地持久化:从本地 SQLite 数据库加载
- 远程持久化:通过 DBus 调用 persistence 服务的
BatchRead方法
数据库路径
本地持久化
maca 和 persistence 服务使用本地 SQLite 数据库:
// 根据 is_mini_system_app 判断路径
if (is_mini_system_app(app_name)) {
// mini_system_app: /data/trust/persistence.local/{app_name}.db
} else {
// 其他服务: /data/opt/bmc/persistence.local/{app_name}.db
}
表名:_t_mc_properties
表结构:
CREATE TABLE _t_mc_properties (
DlogLevel INTEGER, -- 日志级别(数值)
DlogType TEXT, -- 日志输出类型
DlogDuration INTEGER -- 剩余有效时长(半小时数)
)
远程持久化
其他服务通过 DBus 与 persistence 服务通信:
DBus 接口:
- 服务名:
bmc.kepler.persistence - 对象路径:
/bmc/kepler/persistence - 接口:
bmc.kepler.persistence
表名:_t_mc_properties_{app_name}(动态生成)
表结构:
CREATE TABLE _t_mc_properties_{app_name} (
Id INTEGER PRIMARY KEY, -- 主键(固定值 1)
DlogLevel INTEGER, -- 日志级别(数值)
DlogDuration INTEGER -- 剩余有效时长(半小时数)
)
示例数据:
Id=1, DlogLevel=5, DlogDuration=48 -- 24 小时 = 48 个半小时
使用示例
示例 1:服务启动时恢复配置
void micro_component_object::init(mc::string_view service_name)
{
mc::string app_name = mc::app::extract_app_name(service_name);
// 恢复持久化配置(自动判断本地或远程)
auto* svc = get_service();
if (svc) {
mc::string saved_level, saved_type;
uint8_t saved_duration = 0;
if (mc::app::load_debug_config(svc, saved_level, saved_type, saved_duration)) {
m_mc_debug_iface.m_dlog_level = saved_level;
m_mc_debug_iface.m_dlog_type = saved_type;
m_mc_debug_iface.m_dlog_remaining_half_hours = saved_duration;
// 应用日志级别
auto lvl_opt = mc::log::to_level(saved_level.view());
if (lvl_opt) {
mc::log::log_manager::instance().set_dlog_level(*lvl_opt);
ilog("Restored debug log level: ${level}, duration=${duration}h",
("level", saved_level)("duration", static_cast<int>(saved_duration)));
}
}
}
}
示例 2:动态修改并持久化
void set_dlog_level(mc::string level, uint8_t effective_hours)
{
auto lvl_opt = mc::log::to_level(level.view());
if (!lvl_opt) {
elog("Invalid log level: ${level}", ("level", level));
return;
}
// 应用日志级别
mc::log::log_manager::instance().set_dlog_level(*lvl_opt);
// 持久化(自动判断本地或远程)
auto* service = get_service();
if (service) {
mc::app::save_debug_config(service, level,
m_mc_debug_iface.m_dlog_type.value(),
static_cast<uint8_t>(effective_hours * 2));
}
}
编译条件
该模块仅在 MCDBUS_USE_OLD_SHM=1 时可用:
#if defined(MCDBUS_USE_OLD_SHM) && MCDBUS_USE_OLD_SHM
// 完整实现
#else
// 空实现,所有函数返回 false 或空操作
#endif
安全特性
1. SQL 注入防护
所有数据库操作使用参数化查询:
auto stmt = db->prepare("INSERT INTO table VALUES (?, ?, ?)");
stmt->bind_values(mc::variant(level_value), mc::variant(type), mc::variant(duration));
2. 异常处理
所有数据库操作都有 try-catch 保护:
try {
db->exec(create_sql);
db->flush();
} catch (const std::exception& e) {
elog("Failed to save debug config: ${error}", ("error", e.what()));
return;
}
3. 线程安全
配合 micro_component_object 的互斥锁使用:
std::lock_guard<std::mutex> lock(m_dlog_level_mutex);
// 访问 m_dlog_remaining_half_hours