惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

MongoDB | Blog
MongoDB | Blog
大猫的无限游戏
大猫的无限游戏
H
Help Net Security
V
Visual Studio Blog
G
Google Developers Blog
Blog — PlanetScale
Blog — PlanetScale
Last Week in AI
Last Week in AI
C
Check Point Blog
D
Docker
M
MIT News - Artificial intelligence
P
Proofpoint News Feed
博客园 - 叶小钗
博客园 - 聂微东
The Cloudflare Blog
云风的 BLOG
云风的 BLOG
Martin Fowler
Martin Fowler
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
酷 壳 – CoolShell
酷 壳 – CoolShell
MyScale Blog
MyScale Blog
WordPress大学
WordPress大学
Engineering at Meta
Engineering at Meta
腾讯CDC
S
SegmentFault 最新的问题
博客园 - 【当耐特】

OhYee 博客

小鹏辅助驾驶测评|OhYee 博客 小鹏非支持手机开启自动解锁|OhYee 博客 使用函数计算实现 301 重定向|OhYee 博客 针对 HTML 内容使用 Ant Design 图片弹框|OhYee 博客 博客进程泄露及僵尸进程解决|OhYee 博客 蓝易云服务器体验|OhYee 博客 SSH 调起本地 VSCode|OhYee 博客 【2022 秋招内推】阿里云后端研发工程师|OhYee 博客 使用函数计算获取 IP 地址信息|OhYee 博客 正确获取客户端 IP/HTTP Header 也可能重复|OhYee 博客 评测 Oculus Quest2 及 BigScreen|OhYee 博客 NextJS 热重载保留状态|OhYee 博客 如何优雅地贴 gist 代码|OhYee 博客 Linux 精细化文件权限|OhYee 博客 VSCode 容器开发环境|OhYee 博客 Clash 的不兼容更新排查|OhYee 博客 Zeek 导出 PCAP|OhYee 博客 记一次 ssh 配置问题|OhYee 博客 Git Commit 规范化工具|OhYee 博客 谈谈《星之卡比-探索发现》|OhYee 博客 VSCode 快捷键绑定 Shell 命令|OhYee 博客 ASN.1 语法及 X.509 证书格式解析解析|OhYee 博客 腾讯企业邮箱忽略 MX 记录发信|OhYee 博客 Chrome/Edge 标签组插件|OhYee 博客 【应届内推】阿里云后端研发工程师|OhYee 博客 损坏的 Typecho 备份处理为 JSON|OhYee 博客 VS Code VIM 插件高效使用|OhYee 博客 SSH 正反向代理|OhYee 博客 Let's Encrypt 根证书过期引发的问题|OhYee 博客 OpenWRT 忽略内核依赖|OhYee 博客
Tor子系统——日志模块|OhYee 博客
2020-03-09 · via OhYee 博客

日志模块

Tor笔记目录索引

Tor报错模块位于src/lib/log/文件夹

该模块除去对日志输出统一封装外,还实现了针对多线程的日志输出。由于在多线程中,每个线程可能在同一时间输出,如果不对日志输出进行控制,很可能会导致日志混在一起。

该模块用到了smartlist模块,用于实现动态数组。因此,smartlist 模块以及更早的子系统都不能使用日志模块进行日志输出

子系统结构

子系统结构定义解释

const subsys_fns_t sys_logging = {
  .name = "log",
  .supported = true,
  /* Logging depends on threads, approx time, raw logging, and security.
   * Most other lib modules depend on logging. */
  .level = -90,
  .initialize = subsys_logging_initialize,
  .shutdown = subsys_logging_shutdown,
};

初始化子系统

初始化过程中,会初始化互斥锁、以及pending_cb_messagespending_startup_messages两种类型的日志链表

日志类型

严重性等级

Tor 的日志共分为以下几种类型debuginfonoticewarnerr
除此之外,还有critalertemerg几种未用到的日志类型(程序中不会并且不能使用他们)
在大部分函数中,对应的参数为int severity

日志输出模块

在当前版本共有 30 个模块,因此区分一条日志由哪个模块输出也非常重要。比如LD_CRYPTO说明是加密模块输出的日志
在大部分函数中,对应的参数为log_domain_mask_t domain

日志文件

在这里,日志文件不一定就是一个文件,也有可能是一个回调函数
更贴切的理解是:对应的日志等级、模块的处理方法。

如果对应类型的日志要输出的一个文件,则会输出到对应的文件;否则则会则会执行对应的回调函数执行更复杂的操作。

Tor 中,所有的日志文件存储在logfiles变量中

typedef struct logfile_t {
  struct logfile_t *next; // 链表尾指针
  char *filename; // 输出文件名
  int fd; // 输出文件号
  int seems_dead; // 该文件是否可能失效
  int needs_close; // 输出流结束是否需要关闭文件
  int is_temporary; // 是否需要在初始化子系统后关闭文件(临时的日志文件)
  int is_syslog; // 是否是系统日志输出
  int is_android; // 是否是安卓环境
  char *android_tag; // 安卓日志标签
  log_callback callback; // 日志回调
  log_severity_list_t *severities;// 日志对应的模块
} logfile_t;

输出日志

在外部模块中,将使用下面这些函数输出日志:

  • log_debug(domain, args, ...)
  • log_info(domain, args, ...)
  • log_notice(domain, args, ...)
  • log_warn(domain, args, ...)
  • log_err(domain, args, ...)

这些函数将会调用void log_fn_(),对可变参数进行处理,并最终调用logv()执行具体的日志逻辑

flush_pending_log_callbacks

void flush_pending_log_callbacks(void)

该函数会将pending_cb_messages中所有的日志全部处理,并清空等待列表
其中的每一条日志,都会遍历logfiles找到对应的告警级别、模块信息执行对应的回调函数

logv

void logv(int severity, log_domain_mask_t domain, const char *funcname, const char *suffix, const char *format, struct __va_list_tag *ap)

这是各种输出日志的具体执行的函数,首先会调用flush_pending_log_callbacks执行所有的回调日志

接着如果queue_startup_messages未满,则会将当前日志插入进去,并判断该日志在logfiles对应的告警级别、模块信息对应的文件是否需要输出,如果需要则输出到对应的文件中
如果对应的日志存在回调函数,并且该日志不带有LD_NOCB标志时,则会将其插入至pending_cb_messages,否则会直接执行对应的回调函数
如果对应的日志文件既不存在回调函数、不是 Android 环境、不是系统输出,则会输出到日志文件对应的文件中,如果写出失败,则会标记该日志文件可能已经无效

参考资料

  1. Tor源码文件分析 -- Log
  2. Tor 源码分析第三部分—— 日志设施与智能链表