C++日志系统:从原理到实战实现

目录

一.日志

二.日志模拟代码

1.filesystem(C++17封装的文件操作函数)

2.获取当前时间:localtime

[三.FILE LINE](#三.FILE LINE)

[1. FILE](#1. FILE)

[2. LINE](#2. LINE)

四.stringstream


一.日志

计算机中的日志是记录系统和软件运行中发生事件的文件,主要作用是监控运行状态、记录异常信息,帮助快速定位问题并支持程序员进行问题修复。它是系统维护、故障排查和安全管理的重要工具。

日志格式以下几个指标是必须得有的

• 时间戳

• 日志等级

• 日志内容

以下几个指标是可选的

• 文件名行号

• 进程,线程相关id信息等

日志有现成的解决方案,如:spdlog、glog、Boost.Log、Log4cxx等等,我们依旧采用自定义日志的方式。

二.日志模拟代码

1.filesystem(C++17封装的文件操作函数)

<filesystem> 是 C++17 引入的标准库,用于跨平台的文件系统操作(目录遍历、文件读写、路径操作等)

操作 函数
路径操作
拼接路径 path / path
获取父路径 p.parent_path()
获取文件名 p.filename()
获取扩展名 p.extension()
目录操作
创建目录 create_directory() / create_directories()
删除目录 remove() / remove_all()
遍历目录 directory_iterator / recursive_directory_iterator
文件操作
复制文件 copy_file()
移动/重命名 rename()
获取大小 file_size()
查询
存在性 exists()
判断类型 is_* 系列函数
最后修改时间 last_write_time()
路径
绝对路径 absolute()
规范化路径 canonical()
当前工作目录 current_path()

注意事项

  1. C++17 要求:确保编译器启用 C++17 标准

  2. 链接选项 :旧版本 GCC/Clang 需要链接 -lstdc++fs-lc++fs

  3. 跨平台性:路径分隔符自动处理,但根名称(Windows 盘符)存在差异

  4. 性能 :频繁调用 exists()/is_directory() 等,建议使用 directory_entry 缓存版本

  5. 异常安全:注意使用 try-catch 或 error_code 版本

  6. 文件系统竞争:多线程操作同一文件系统对象时行为未定义

2.获取当前时间:localtime

在日志中我们难免不了获取当前的时间,下面展示一个简单快速的获取当前可读性高的时间的方法·。

localtime_r 是线程安全的日期时间转换函数,用于将时间戳转换为本地时间的结构化表示

cpp 复制代码
#include <time.h>    // C
#include <ctime>     // C++
cpp 复制代码
struct tm* localtime_r(const time_t* timep, struct tm* result);
参数 类型 说明
timep const time_t* 指向时间戳的指针(通常来自 time() 函数)
result struct tm* 指向存储结果的 tm 结构体的指针
  • 成功 :返回 result 指针(即第二个参数)

  • 失败 :返回 NULL

三.FILE LINE

预定义宏是编译器在编译过程中自动定义的特殊宏,它们在预处理阶段被替换为对应的值。这些宏都以双下划线开头和结尾。

1. __FILE__

类型 : const char*(字符串字面量)

: 当前源文件的文件名(包含路径)

cpp 复制代码
// 文件: /home/user/project/src/main.cpp
#include <iostream>
int main() {
    std::cout << __FILE__ << std::endl;
    // 输出: /home/user/project/src/main.cpp
    return 0;
}

2. __LINE__

类型 : int(整数常量)

: 当前代码所在的行号

cpp 复制代码
#include <iostream>
int main() {
    std::cout << __LINE__ << std::endl;  // 输出: 4
    std::cout << __LINE__ << std::endl;  // 输出: 5
    return 0;
}
  • 行号从 1 开始计数

  • 空行、注释也会占用行号

  • 可以通过 #line 指令修改

四.stringstream

stringstream 是 C++ 标准库中用于字符串流处理的类,定义在 <sstream> 头文件中。它允许你将字符串像输入输出流一样操作。

stringstream 继承自 iostream,因此它支持 <<>> 操作符,可以将各种数据类型转换为字符串或从字符串解析。

cpp 复制代码
#include <sstream>
#include <iostream>
#include <string>

// 1. stringstream - 可读可写
std::stringstream ss;

// 2. istringstream - 只读(输入)
std::istringstream iss("Hello World");

// 3. ostringstream - 只写(输出)
std::ostringstream oss;
cpp 复制代码
std ::stringstream ssbuffer;
                ssbuffer << "[" << _currtime << "] "
                         << "[" << LevaltoString(_leval) << "] "
                         << "[" << _pid << "] "
                         << "[" << _filename << "] "
                         << "[" << _line << "]"
                         << " - ";

                _loginfo = ssbuffer.str();

与snpringf的功能类似。

相关推荐
Chase_______39 分钟前
【Java基础 | 11】异常处理进阶:throw、throws、自定义异常与异常链讲清楚
java·开发语言·python
DFT计算杂谈40 分钟前
VASP 磁性结构可视化:一键生成完美 VESTA / MCIF
java·前端·css·html·css3
tg:;43 分钟前
Catkin 常用命令
开发语言·c++·算法
Cx330❀1 小时前
【Linux网络】一文吃透 TCP Socket 编程
linux·运维·服务器·开发语言·网络·tcp/ip
砍材农夫1 小时前
物联网实战:Spring Boot MQTT | 模拟器Paho客户端拆解核心点
java·javascript·网络·spring boot·后端·物联网
weixin_539446781 小时前
使用Java HttpServletResponse和JavaScript Fetch下载文件
java·javascript·python
我登哥MVP1 小时前
Spring Boot 从“会用”到“精通”:自动装配原理
java·spring boot·后端·spring·tomcat·maven·intellij-idea
wb043072011 小时前
外卖大战——从阿明的“3 秒生死线“,看系统性能优化的全链路方法论
开发语言·性能优化·架构·php
小的~~1 小时前
Java线程及线程池的相关的问题
java·开发语言·多线程
爱吃羊的老虎1 小时前
【JAVA】Java微服务—网关Gateway
java·微服务·gateway