Vala日志添加时间戳及日志级别控制问题求助
我明白你的困境——在eOS Loki的Glib 2.48环境下,没法用set_writer_func来自定义日志格式,而且现有代码虽然能输出带时间戳的日志,但级别过滤完全失效。其实问题出在你没有在自定义日志逻辑里手动实现级别检查,毕竟默认的日志过滤逻辑是绑定在默认处理器上的,替换成自定义逻辑后得自己补上这部分。
下面是适配Glib 2.48的完整解决方案,用Log.set_handler(这个API在2.48里完全可用)来实现带时间戳的日志,同时严格遵守级别过滤规则:
完整示例代码
using GLib; public class AppLogger { // 定义允许输出的日志级别:这里设为INFO及以上(DEBUG会被过滤) private static LogLevelFlags _allowed_levels = LogLevelFlags.INFO | LogLevelFlags.MESSAGE | LogLevelFlags.WARNING | LogLevelFlags.CRITICAL | LogLevelFlags.ERROR | LogLevelFlags.FATAL; // 初始化日志处理器 public static void init() { // 注册全局日志处理器(替换默认输出逻辑) Log.set_handler(null, LogLevelFlags.ALL, (domain, level, message) => { // 第一步:过滤掉不符合级别的日志 if ((level & _allowed_levels) == 0) { return; // 直接返回,不输出 } // 第二步:格式化时间戳 DateTime now = DateTime.now_local(); string timestamp = now.format("%Y-%m-%d %H:%M:%S.%f"); // 精确到毫秒 // 第三步:获取易读的级别名称 string level_name = switch (level) { case LogLevelFlags.DEBUG: "DEBUG"; break; case LogLevelFlags.INFO: "INFO"; break; case LogLevelFlags.MESSAGE: "MESSAGE"; break; case LogLevelFlags.WARNING: "WARNING"; break; case LogLevelFlags.CRITICAL: "CRITICAL"; break; case LogLevelFlags.ERROR: "ERROR"; break; case LogLevelFlags.FATAL: "FATAL"; break; default: "UNKNOWN"; break; }; // 第四步:输出格式化后的日志 print(@"[$timestamp] [$level_name] $message\n"); }); } // 可以添加一个方法动态修改日志级别 public static void set_allowed_levels(LogLevelFlags levels) { _allowed_levels = levels; } } public int main(string[] args) { AppLogger.init(); // 测试日志输出 debug("这条DEBUG日志应该被过滤"); info("这条INFO日志会正常显示"); warning("这条WARNING日志也会显示"); error("这条ERROR日志同样会显示"); // 如果需要临时开启DEBUG级别,可以调用: // AppLogger.set_allowed_levels(LogLevelFlags.ALL); // debug("现在DEBUG日志也能输出了"); return 0; }
关键要点说明
级别过滤逻辑:
核心是在自定义处理器里判断level & _allowed_levels是否为0——如果是0,说明当前日志级别不在允许范围内,直接跳过输出。你可以通过修改_allowed_levels来灵活控制要输出的日志等级,比如要开启DEBUG就改成LogLevelFlags.ALL。兼容Glib 2.48:
Log.set_handler是Glib很早就支持的API,完全适配2.48版本,不需要依赖2.50+的set_writer_func。时间戳格式化:
用DateTime.now_local()获取本地时间,通过format()方法自定义时间格式,示例里用了%Y-%m-%d %H:%M:%S.%f来输出精确到毫秒的时间戳,你可以根据需求调整格式。全局/域特定处理:
示例里用null作为日志域(domain),表示处理所有全局日志。如果你的应用有特定的日志域,可以把null换成你的域名称,比如"my-eos-app",这样只会处理该域下的日志,更精准。
为什么你的旧代码级别过滤失效?
因为当你替换了默认日志处理器后,Glib自带的级别过滤逻辑就不会生效了——默认处理器会自动检查日志级别是否符合设置,但自定义处理器需要你自己实现这部分判断逻辑,否则所有日志都会被输出。
内容的提问来源于stack exchange,提问作者Siddhartha Das

