1.Gin源码分析 - 中间件(3)- Logger
2.easylogging源码学习笔记(6)
3.如何从零写一个日志库(glog介绍)
4.c++日志库实战——spdlog,日志日志感觉log4cxx有点笨重,控件控件不妨试一试spdlog
5.element-plus源码学习日志-03
6.剖析slf4j原理并实现自己的源码源码用日志框架
Gin源码分析 - 中间件(3)- Logger
本文深入剖析Gin框架内置中间件Logger,详细阐述其四种创建形式。日志日志基本形式以默认配置输出日志至标准输出。控件控件自定义格式器形式允许用户调整日志输出格式。源码源码用硬盘逻辑锁源码指定输出流形式则灵活地将日志输出至特定写入器,日志日志同时可忽略指定路径的控件控件日志。复杂配置形式提供高度定制化,源码源码用是日志日志创建中间件的高级手段。深入探讨LoggerConfig结构体,控件控件解析其三个关键属性:日志格式、源码源码用输出器和忽略路径。日志日志LogFormatter方法实现日志的控件控件格式化,包含辅助函数进行颜色调整,源码源码用如根据HTTP响应码和请求类型设置显示颜色。defaultLogFormatter方法提供默认的日志格式化操作。详细解析LoggerWithConfig方法,该方法获取配置参数并判断输出环境,随后将忽略路径保存为映射,记录过滤的路径。计算处理时间和构建日志字符串,长沙app源码输出至指定写入器。
easylogging源码学习笔记(6)
`LOG` 是默认日志、CLOG自定义日志、LOG_IF条件日志
特殊日志
LOG_EVERY_N、LOG_AFTER_N、LOG_N_TIMES
for (int i = 1; i <= ; ++i) {
LOG_EVERY_N(2, INFO) << "Logged every second iter";
}// 5 logs written; 2, 4, 6, 7,
for (int i = 1; i <= ; ++i) {
LOG_AFTER_N(2, INFO) << "Log after 2 hits; " << i;
}// 8 logs written; 3, 4, 5, 6, 7, 8, 9,
for (int i = 1; i <= ; ++i) {
LOG_N_TIMES(3, INFO) << "Log only 3 times; " << i;
}// 3 logs writter; 1, 2, 3
条件日志和特殊日志可以搭配使用
* `VLOG_IF(condition, verbose-level)`
* `CVLOG_IF(condition, verbose-level, loggerID)`
* `VLOG_EVERY_N(n, verbose-level)`
* `CVLOG_EVERY_N(n, verbose-level, loggerID)`
* `VLOG_AFTER_N(n, verbose-level)`
* `CVLOG_AFTER_N(n, verbose-level, loggerID)`
* `VLOG_N_TIMES(n, verbose-level)`
* `CVLOG_N_TIMES(n, verbose-level, loggerID)`
日志详细等级判定
if (VLOG_IS_ON(2)) {
// Verbosity level 2 is on for this file
}
性能追踪
* `TIMED_FUNC(obj-name)`
* `TIMED_SCOPE(obj-name, block-name)`
* `TIMED_BLOCK(obj-name, block-name)`
这些宏实际上都是关于el::base::type::PerformanceTrackerPtr,一个指向el::base::PerformanceTracker的指针
#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING)
PerformanceTracker::PerformanceTracker(const std::string& blockName,
base::TimestampUnit timestampUnit,
const std::string& loggerId,
bool scopedLog, Level level) :
m_blockName(blockName), m_timestampUnit(timestampUnit), m_loggerId(loggerId), m_scopedLog(scopedLog),
m_level(level), m_hasChecked(false), m_lastCheckpointId(std::string()), m_enabled(false) {
#if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED
// We store it locally so that if user happen to change configuration by the end of scope
// or before calling checkpoint, we still depend on state of configuration at time of construction
el::Logger* loggerPtr = ELPP->registeredLoggers()->get(loggerId, false);
m_enabled = loggerPtr != nullptr && loggerPtr->m_typedConfigurations->performanceTracking(m_level);
if (m_enabled) {
base::utils::DateTime::gettimeofday(&m_startTime);
}
#endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED
}
在构造函数中获取一个时间,
PerformanceTracker::~PerformanceTracker(void) {
#if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED
if (m_enabled) {
base::threading::ScopedLock scopedLock(lock());
if (m_scopedLog) {
base::utils::DateTime::gettimeofday(&m_endTime);
base::type::string_t formattedTime = getFormattedTimeTaken();
PerformanceTrackingData data(PerformanceTrackingData::DataType::Complete);
data.init(this);
data.m_formattedTimeTaken = formattedTime;
PerformanceTrackingCallback* callback = nullptr;
for (const std::pair& h
: ELPP->m_performanceTrackingCallbacks) {
callback = h.second.get();
if (callback != nullptr && callback->enabled()) {
callback->handle(&data);
}
}
}
}
#endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING)
}
在析构函数中获取一个时间,处理时间data,使用PerformanceTrackingCallback类型指针callback,并在callback->handle(&data)中处理输出。
由于定义了ELPP_FEATURE_PERFORMANCE_TRACKING,因此在初始化(INITIALIZE_EASYLOGGINGPP)中实际上是安装了一个base::DefaultPerformanceTrackingCallback。
在PerformanceTracker类的handle函数中,callback是一个PerformanceTrackingCallback类型指针,由于安装的是DefaultPerformanceTrackingCallback对象,因此是一个基类指针指向了派生类对象。处理输出的逻辑在DefaultPerformanceTrackingCallback类的handle函数中。
DefaultPerformanceTrackingCallback类的handle函数首先会将数据成员m_data的指针赋值给函数参数,并创建一个base::type::stringstream_t类型的对象ss用于构建输出内容。根据m_data的长波操作源码dataType,输出不同的信息。在输出时,会使用el::base::Writer类构造并输出内容。
如何从零写一个日志库(glog介绍)
探索日志管理的艺术,本文将深入解析glog——谷歌开源的日志库,为你揭示从零开始构建自定义日志解决方案的关键要素。让我们一起从基本需求到高级接口,一窥其内部工作原理。基本需求与核心组件
glog的核心在于LogMessage类,它负责记录日志的时间、位置信息以及根据过滤条件进行输出。0.3.5版本作为起点,提供了诸如LOG、LOG_IF和LOG_TO_SINK等接口,让你能灵活定制输出到默认目标或自定义sink。 获取glog的源代码:/google/glog.git,源码中的src/glog//gabime/spdlog),并按照官方文档快速入门。spdlog的安装与集成主要通过CMake或Vcpkg进行,以确保项目中拥有所需的功能。手动编译时,线路指标源码通过CMake命令生成的makefile进行编译,若机器上未安装CMake,需要先进行安装(例如使用cmake3..5在macos .上)。若使用Vcpkg,则需确保其安装,并执行相应的安装和配置步骤。
在实际使用中,我遇到了一些问题,例如配置错误、日志格式化问题等。参考官方文档或相关教程,我得以解决并优化了日志系统。推荐的教程包括如何设计高效日志库、C++高性能日志库设计与实现,以及C++后端必读的开源项目源码等。
在项目实战中,我创建了SpdlogWarper,包含log.h与Log.cpp,实现了日志功能的封装与调用。其中,关于日志打印行号、短线神器源码控制台日志显示、控制台与文件同时输出以及停止调试时的日志问题,官方文档提供了具体解决方案。
例如,通过设置默认logger为控制台,可以实现控制台输出日志。同时输出控制台与文件日志时,需注册并配置相应的logger。在处理文件按天分割和停止调试时的日志丢失问题时,通过配置定时刷新或设置特定触发条件(如error级别)进行flush操作,以确保日志文件的完整性和稳定性。
在进行完整代码实现时,控制台输出与文件输出的配置需根据实际需求进行调整,确保日志信息的清晰、完整与高效。
总结而言,通过将日志系统从log4cxx迁移到spdlog,我在新项目中实现了更高效、更简洁的日志管理,解决了之前的性能瓶颈和功能局限。spdlog的灵活性、高性能与丰富的文档支持,使其成为C++项目中日志处理的优选组件。
element-plus源码学习日志-
在element-plus的源码探索系列中,今天的重点转向了Dialog组件和Vue3的新特性。首先,我们来到element-plus\packages\dialog\src\index.vue,研究内置的teleport组件。
teleport是个强大的工具,它能让原本作为子组件的DOM元素,通过to属性的指定,直接定位到应用的同级节点,甚至body下。这对于解决层级问题,特别是实现全局弹层时,非常重要。在Vue2时代,我们曾用Vue.extend来创建并挂载在顶层的自定义组件,teleport简化了这一过程。
接着,我们注意到vue3的自定义指令有所更新,涉及生命周期的变动。虽然具体细节还未详尽理解,但官方文档的说明有待后续深入研究。由于vue3支持fragments,组件不再受限于单一节点,这带来了新的挑战,目前暂存疑问。
在代码部分,我们回顾了之前讲解过的内容,通过实际例子,复习了相关知识。今天的收获包括对teleport的深入理解,以及对新版本自定义指令的初步接触。
最后,计划在下篇中,我们将学习如何基于Jest为组件编写单元测试,包括基本用法和测试报告的生成,这是框架开发中的关键步骤。
剖析slf4j原理并实现自己的日志框架
本文深入探讨了SLF4J的基本原理,并展示了如何实现自己的日志框架。SLF4J作为日志系统的一个适配层,其主要作用是解决日志系统选择和配置的复杂性。通过引入SLF4J,开发人员只需关注日志的编写逻辑,而无需关心日志系统的具体实现。SLF4J并不提供日志的直接实现,而是提供了一套接口以及获取具体日志对象的方法。SLF4J的实现包括SLF4J-SIMPLE、Logback和Log4j等。Logback和Log4j通过特定的桥接层与SLF4J兼容。
本文详细分析了Logback的源码结构,展示了它如何基于门面模式实现日志接口,以及Log4j如何通过SLF4J-log4j桥接层与SLF4J进行交互。通过对比SLF4J-API与SLF4J-SIMPLE,本文进一步解释了SLF4J作为适配层的灵活性与重要性。在使用SLF4J时,多个实现可能会导致冲突,通过配置管理或更新依赖关系可以解决这类问题。
通过实例分析,本文揭示了SLF4J如何帮助开发者在项目中引入不同的日志实现,并确保在更换或维护日志系统时的简便性。SLF4J的实现过程包括定义门面对象、实现自己的LoggerFactory和Logger,最终通过StaticLoggerBinder获取具体的Logger实例。
实现自己的日志框架时,确保包名遵循SLF4J的查找规则至关重要。本文提出了实现日志框架的三大关键组件:定义包名、实现自定义的LoggerFactory和Logger。SLF4J的原理分析指出,其核心在于performInitialization()方法的执行,进而通过StaticLoggerBinder实现具体日志系统的获取。
对于不改变原有代码而引入自己的日志框架,本文建议通过切面编程实现,确保该类被Spring管理且非null。在SpringBoot2.x中,通常使用cglib进行代理实现。项目已开源,欢迎读者指出错误,地址:gitee.com/z_w/LogSys...
日志代码怎么查看啊
要查看日志代码,无论是别人的还是自己的,步骤各有不同。
对于查看别人的日志代码,你只需在当前页面上右击鼠标,选择“查看源代码”选项,页面会显示包含代码的文本区域,这样你就能查看到日志代码的具体内容了。
而如果你想查看自己的日志代码,操作则相对简单一些。只需打开文章编辑界面,找到并勾选“显示源代码”的选项,页面同样会展示代码区域,帮助你了解日志代码的编写。
以上就是查看日志代码的基本方法,无论是查看别人的还是自己的日志,都可通过上述步骤轻松实现。