Chromium源码阅读(9):了解Log模块

news2024/9/23 1:33:17

Chromium许多日志被TraceEvent代替了,因此TraceEvent出现的频率要比Log高很多。
但是也有不少场景使用Log。
在blink,Log的实现由base提供,而blink/render/core/base/logging.h进行了二次封装。

日志系统的设计细节

错误对话框处理

  • 错误消息显示: 当应用程序遇到断言失败或致命错误时,默认情况下会弹出一个对话框展示错误信息。然而,这个UI的创建会导致消息循环,这可能使应用在不好的状态中处理或分发消息到现有窗口,导致挂起或异常行为。
  • 分离进程显示错误: 为了避免上述问题,可以在与主应用程序相同的目录下创建一个名为DebugMessage.exe的独立程序,用于专门显示致命错误对话框。这样即使主程序处于不稳定状态,错误信息也能正确显示而不影响主程序的其他部分。
  • 简化命令行解析: 此独立程序接收错误信息作为命令行参数,不会包含应用程序名称,以便于解析。

日志宏

  • 基本日志: 提供了一系列宏,如LOG(INFO),用于在不同严重级别下记录日志信息。
  • 条件日志: 可以使用LOG_IF(INFO, condition)根据条件记录日志。
  • 断言宏: CHECK(condition)在所有构建模式下都有效,如果条件不满足,则记录FATAL级别的日志并终止程序。

调试模式日志

  • 调试宏: DLOG(INFO)仅在调试模式下生效,而在非调试模式下会被编译器忽略。
  • 调试断言: DLOG_ASSERT(condition)在调试模式下工作,类似于CHECK

详细日志

  • 详细级别日志: VLOG(1)允许根据不同的详细级别记录日志,可以通过运行参数--v=<level>开启。
  • 模块特定日志: 可以指定特定模块的详细级别,例如--vmodule=profile=2
  • 通配符支持: 模块名可以使用通配符*?匹配多个文件或目录下的源文件。

其他特性

  • 系统错误日志: PLOG(ERROR)附加系统错误信息到日志中。
  • 特殊日志级别: DFATALDCHECK启用的构建中等同于FATAL,在普通构建中为ERROR
  • 格式化输出: 日志输出包括PID、TID、日期时间、日志级别、文件名及行号等信息。

配置和偏好设置

  • 用户可以通过SetLogItems()函数调整日志的可见性。
  • 在Chrome OS上,日志输出可以切换到syslog-like格式。

LOG_STREAM

在实际打印日志的时候,是以流式打印的,例如:

LOG(INFO) << "Found " << num_cookies << " cookies";

LOG宏定义如下:


// We use the preprocessor's merging operator, "##", so that, e.g.,
// LOG(INFO) becomes the token COMPACT_GOOGLE_LOG_INFO.  There's some funny
// subtle difference between ostream member streaming functions (e.g.,
// ostream::operator<<(int) and ostream non-member streaming functions
// (e.g., ::operator<<(ostream&, string&): it turns out that it's
// impossible to stream something like a string directly to an unnamed
// ostream. We employ a neat hack by calling the stream() member
// function of LogMessage which seems to avoid the problem.
#define LOG_STREAM(severity) COMPACT_GOOGLE_LOG_ ## severity.stream()

#define LOG(severity) LAZY_STREAM(LOG_STREAM(severity), LOG_IS_ON(severity))
#define LOG_IF(severity, condition) \
  LAZY_STREAM(LOG_STREAM(severity), LOG_IS_ON(severity) && (condition))

// The VLOG macros log with negative verbosities.
#define VLOG_STREAM(verbose_level) \
  ::logging::LogMessage(__FILE__, __LINE__, -(verbose_level)).stream()

这段代码的解读如下:

  1. LOG_STREAM 宏:

    #define LOG_STREAM(severity) COMPACT_GOOGLE_LOG_ ## severity.stream()
    

    这个宏接受一个参数severity,它是一个日志级别(例如,INFO、ERROR等)。宏中的##是C++预处理器的字符串拼接操作符,它会将两个独立的标识符拼接成一个新的标识符。因此,LOG_STREAM(severity)被展开为COMPACT_GOOGLE_LOG_severity.stream()

  2. LOG 和 LOG_IF 宏:

    #define LOG(severity) LAZY_STREAM(LOG_STREAM(severity), LOG_IS_ON(severity))
    #define LOG_IF(severity, condition) \
      LAZY_STREAM(LOG_STREAM(severity), LOG_IS_ON(severity) && (condition))
    

    这些宏用于实际的日志输出。LOGLOG_IF都会调用LAZY_STREAM宏,其中LOG_STREAM(severity)提供了日志流对象,而LOG_IS_ON(severity)检查日志级别是否被启用。LOG_IF则额外检查一个条件condition,只有当这个条件为真时才进行日志记录。

  3. VLOG 和 VLOG_STREAM 宏:

    #define VLOG_STREAM(verbose_level) \
      ::logging::LogMessage(__FILE__, __LINE__, -(verbose_level)).stream()
    #define VLOG(verbose_level) \
      LAZY_STREAM(VLOG_STREAM(verbose_level), VLOG_IS_ON(verbose_level))
    

    VLOG宏用于更详细的日志记录,通常用于调试。VLOGVLOG_STREAM接受一个verbose_level参数,表示日志的详细程度。VLOG_STREAM创建一个LogMessage对象,并通过传递文件名、行号和负数的verbose_level来控制日志的详细度。VLOG宏同样使用LAZY_STREAM来决定是否真正执行日志记录,这依赖于VLOG_IS_ON(verbose_level)的值。这种设计允许在编译时优化掉未启用的日志输出,从而提高运行时性能。

base 的 Log

Chromium的base模块里也有一个Log模块
【未完待续 … 】

absel的Log

在一些底层模块,更倾向于直接调用abseil-cpp\absl\log的日志模块,其使用方式也和上面大同小异。宏展开之后如下:
在这里插入图片描述
为什么这个宏要用switch-case的形式呢?这里有说明:


// `ABSL_LOG_INTERNAL_CONDITION` prefixes another macro that expands to a
// temporary `LogMessage` instantiation followed by zero or more streamed
// expressions.  This definition is tricky to read correctly.  It evaluates to
// either
//
//   (void)0;
//
// or
//
//   ::absl::log_internal::Voidify() &&
//       ::absl::log_internal::LogMessage(...) << "the user's message";
//
// If the condition is evaluable at compile time, as is often the case, it
// compiles away to just one side or the other.
//
// Although this is not used anywhere a statement (e.g. `if`) could not go,
// the ternary expression does a better job avoiding spurious diagnostics
// (dangling else, missing switch case) and preserving noreturn semantics (e.g.
// on `LOG(FATAL)`) without requiring braces.
//
// The `switch` ensures that this expansion is the begnning of a statement (as
// opposed to an expression) and prevents shenanigans like
// `AFunction(LOG(INFO))` and `decltype(LOG(INFO))`.  The apparently-redundant
// `default` case makes the condition more amenable to Clang dataflow analysis.
#define ABSL_LOG_INTERNAL_STATELESS_CONDITION(condition) \
  switch (0)                                             \
  case 0:                                                \
  default:                                               \
    !(condition) ? (void)0 : ::absl::log_internal::Voidify()&&

简而言之,switch (0)确保宏展开后的代码始终从一个合法的语句开始,而不是表达式。这防止了诸如AFunction(LOG(INFO))或decltype(LOG(INFO))这样的非法用法。
case 0后面跟default,是为了默认情况使条件更适合Clang执行流分析,使得代码被优化得更好。

日志的写入架构

日志没什么缓存,判断认为该写文件的就马上写文件了,这样的设计也是为了避免崩溃的时候日志不全。缓存的事情应该由操作系统的文件系统去处理:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1934244.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt第十二章 样式表

样式表 文章目录 样式表1.样式表盒子模型 2.选择器选择器类型伪状态选择器Pseudo-State 3.控件示例4继承自QWidget的类&#xff0c;设置qss样式表没有效果&#xff0c;需要重写paintEvent 1.样式表 盒子模型 2.选择器 样式表语法&#xff0c;选择器{属性1:值;属性2:值;}如果只…

韦东山嵌入式linux系列-驱动进化之路:设备树的引入及简明教程

1 设备树的引入与作用 以 LED 驱动为例&#xff0c;如果你要更换LED所用的GPIO引脚&#xff0c;需要修改驱动程序源码、重新编译驱动、重新加载驱动。 在内核中&#xff0c;使用同一个芯片的板子&#xff0c;它们所用的外设资源不一样&#xff0c;比如A板用 GPIO A&#xff0c…

鸿蒙仓颉语言【类型class】

类与结构&#xff08;class & struct&#xff09; 面向对象的编程语言&#xff0c;必不可少的基础元素&#xff0c;类或者叫类型&#xff0c;在仓颉中类可以抽象(abstract)、继承&#xff08;<:&#xff09;&#xff0c;公开&#xff08;Public&#xff09;或者私有&am…

在jsPsych中使用Vue

jspsych 介绍 jsPsych是一个非常好用的心理学实验插件&#xff0c;可以用来构建心理学实验。具体的就不多介绍了&#xff0c;大家可以去看官网&#xff1a;https://www.jspsych.org/latest/ 但是大家在使用时就会发现&#xff0c;这个插件只能使用js绘制界面&#xff0c;或者…

【算法专题】归并排序

目录 1. 排序数组 2. 交易逆序对的总数 3. 计算右侧小于当前元素的个数 4. 翻转对 总结 1. 排序数组 912. 排序数组 - 力扣&#xff08;LeetCode&#xff09; 今天我们使用归并排序来对数组进行排序&#xff0c;实际上&#xff0c;归并排序和快速排序是有一定相似之处的&a…

什么是蓝牙芯片?蓝牙芯片和蓝牙模块的区别

蓝牙芯片&#xff0c;是一种集成了蓝牙无线通信技术的微型电子元件。它如同一个微小的通信枢纽&#xff0c;能够在各种电子设备之间建立无线连接&#xff0c;实现数据的传输与共享。蓝牙芯片的设计精妙而复杂&#xff0c;内部集成了射频前端、数字基带、协议栈等多个功能模块&a…

Linux中nohup(no hang up)不挂起,用于在系统后台不挂断地运行命令,即使退出终端也不会影响程序的运行。

nohup的英文全称是 no hang up&#xff0c;即“不挂起”。这个命令在Linux或Unix系统中非常有用&#xff0c;主要用于在系统后台不挂断地运行命令&#xff0c;即使退出终端也不会影响程序的运行。默认情况下&#xff08;非重定向时&#xff09;&#xff0c;nohup会将输出写入一…

linux中常见的协议、服务端口整理汇总

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 ​ &#x1f3c5;阿里云ACE认证高级工程师 ​ &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社…

排序系列 之 插入排序

&#xff01;&#xff01;&#xff01;排序仅针对于数组哦本次排序是按照升序来的哦 介绍 插入排序英文名为InsertSort 基本思路 1、认为数组当中的第一个数值已经排好序了2、定义一个游标从第二个数值开始不断地向后进行遍历3、游标指向的数据插入已经排好序的数组中 代码…

力扣刷题之2959.关闭分部的可行集合数目

题干描述 一个公司在全国有 n 个分部&#xff0c;它们之间有的有道路连接。一开始&#xff0c;所有分部通过这些道路两两之间互相可以到达。 公司意识到在分部之间旅行花费了太多时间&#xff0c;所以它们决定关闭一些分部&#xff08;也可能不关闭任何分部&#xff09;&…

AV1 编码标准屏幕内容编码技术概述

AV1 屏幕内容编码 为了提高屏幕捕获内容的压缩性能&#xff0c;AV1采用了几种编码工具&#xff0c;例如用于处理屏幕画面中重复模式的内帧内块复制&#xff08;IntraBC&#xff09;&#xff0c;以及用于处理颜色数量有限的屏幕块的调色板模式。 帧内块拷贝 AV1 编码中的 Intra …

【Vue】快速入门:构建你的第一个Vue 3应用

文章目录 一、Vue简介二、环境搭建1. 安装Node.js和npm2. 安装Vue CLI 三、创建Vue项目四、项目结构介绍五、组件基础创建一个组件使用组件 六、模板语法插值指令v-bindv-ifv-for 七、事件处理八、状态管理安装Vuex创建Store使用Store 九、路由基础安装Vue Router配置路由使用路…

FFmpeg播放视频

VS2017+FFmpeg6.2.r113110+SDL2.30.5 1.下载 ShiftMediaProject/FFmpeg 2.下载SDL2 3.新建VC++控制台应用 3.配置include和lib 4.把FFmpeg和SDL的dll 复制到工程Debug目录下,并设置调试命令

24年Hvv准备,6大方向,33篇技战法

进去不少小伙伴后台留言说需要技战法&#xff0c;因此小编对市面上的技战法进行了收集和总结&#xff0c;并对收集来的技战法进行了分类&#xff0c;总共分了6大类&#xff0c;共计33篇&#xff1a; 有需要的小伙伴关注我&#xff0c;点击在看&#xff0c;并私信回复“技战法”…

IO、进程、线程03

第一题&#xff1a;预习 opendir 和 readdir函数 opendir 和 readdir 是两个在C语言&#xff08;特别是使用POSIX标准的系统&#xff0c;如Linux和UNIX&#xff09;中用于目录遍历的函数。这两个函数属于标准的C库中的目录操作部分&#xff0c;通常与<dirent.h>头文件一…

MySQL学习记录 —— 이십일 MySQL服务器文件系统(1)

文章目录 1、配置和默认值2、系统变量和选项1、介绍2、常用选项3、如何使用系统变量 3、常用服务器配置4、查看状态变量5、MySQL数据目录 mysql的服务端就是mysqld&#xff0c;d就是daemon&#xff0c;守护进程的意思。 配置文件中[mysqld]部分时服务器支持的启动选项。服务器…

某航空制造业集团IT信息化总体规划方案

获取完整方案见下图 更多有关华为研发管理/IPD、MBSE、PLM、ERP、MES、数据治理、数字样机等方面免费解决方案、资料获取&#xff0c;请见下图

开放式耳机哪个品牌好?开放式耳机实用推荐

开放式耳机是一种耳机类型&#xff0c;其外壳是开放的&#xff0c;发声单元的背面和外界相通。这种耳机的外壳上通常有许多小孔或者直接能够看到内部的发声单元。 而且开放式耳机几乎摒弃了传统耳机几乎所有缺点&#xff01;&#xff01; ❌有线耳机&#xff1a;运动的时候特别…

如何走出低能量状态?

晚上好。 每个人都难免会有状态不佳的时候。可能是遭受压力&#xff0c;可能是事情不顺&#xff0c;也可能无缘无故、突然就陷入情绪的低谷之中。 这时&#xff0c;我们很容易感到精力不济&#xff0c;无精打采&#xff0c;明明有许多事情要做和想做&#xff0c;但总是提不起精…

宠物空气净化器哪款品牌好?口碑好的猫用空气净化器排名

猫咪每年掉毛两次&#xff0c;一次掉半年的现象真让人头疼。作为一位5年资深铲屎官&#xff0c;特别是在掉毛季节&#xff0c;猫毛无处不在&#xff0c;对此深有体会。宠物空气净化器已成为铲屎官们的救星&#xff0c;能迅速清理家中的宠物毛发和异味&#xff0c;是养猫家庭的必…