【C++模块实现】| 【06】日志模块添加循环覆盖写文件功能

本文介绍了如何在C++中实现一个日志系统,包括循环覆盖写文件功能的添加。作者提出了两种实现方法,一种是根据文件修改时间选择最旧的文件进行覆盖,另一种是通过配置文件记录当前文件编号。在实现过程中遇到了文件大小限制未生效和配置文件更新格式错误的问题,并给出了相应的解决方案。测试表明,改进后的日志系统能够正常工作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

========》以下全部代码查看《========

索引

【C++模块实现】| 【01】日志系统实现
【C++模块实现】| 【02】日志系统优化
【C++模块实现】| 【03】文件管理模块
【C++模块实现】| 【04】配置模块
【C++模块实现】| 【05】日志模块增加配置模块的功能
【C++模块实现】| 【06】日志模块添加循环覆盖写文件功能
【C++模块实现】| 【07】对于互斥、自旋锁、条件变量、信号量简介及封装
【C++模块实现】| 【08】循环覆盖写内存缓冲区(日志中多线程记录)
【C++模块实现】| 【09】线程模块及线程池的实现
【C++模块实现】| 【10】定时器的实现
【C++模块实现】| 【11】封装Ipv4、Ipv6、unix网络地址

1、简介

结合前面的配置模块,我们已经将日志系统的配置项通过配置模块进行加载;
但该日志系统中没有提供循环覆盖写文件功能,故本节将参考网上一些文章对其进行完善;
结合参考的文章,做出了一些简单的循环覆盖写文件:
首先配置中设定日志保存的期限、日志文件的内存上限以及扩张的文件数(log1.txt、log2.txt),可以有多种方式,可以按时间进行文
件划分,但本次只简单的设置按个数划分;
方法一:通过检查文件每个文件的日期,若文件数没有到达限制个数,则创建它做为日志副本;
		否则直接将文件修改日志最小的(即最早生成的)作为日志的存储副本;
【如:】若限定最多生成5个文件数(log1.txt、log2.txt、log3.txt、log4.txt、log5.txt),日志只往log.txt中写入,
	当log.txt写满时,将遍历这5个文件,若文件不存在,则直接移动到该文件,若存在,则移动到文件修改日期最早的那个文件;

方法二:
	在配置中增添一项用来记录日志更新到第几个文件数file_num;
	当log.txt文件写满时,先检查各个文件日志是否存在,若存在则检查是否过期,若过期则删除,且log.txt日志直接移动到
	该日志文件中,若不存在,则log.txt直接移动到该日志文件中,若满足期限且存在,则移动到logfile_num.txt中;
	该file_num若有变动,则会对配置文件进行更新记录,便于下次加载;

上述方法测试,暂时没有问题,只是简单的实现,若有其他缺漏,或方法不适用,麻烦各位指点。

2、遇到的问题

2.1 日志文件大小的限制没有达到预期的要求
在这里插入图片描述

每次进入该判断时,文件大小是正确的,但后续对文件进行移动的时候却显示文件的大小远大于该限制;
后面发现没有对该文件进行关闭操作,应该是缓冲区中的内容还没有写入到文件中导致的;
后续在此处对文件关闭即解决

2.2 yamlstring

当配置项的内容有更新时,需要回写到配置文件时,将YAML::Node格式的内容压入stringstream中后写入文件格式出现问题;
后续提供toYaml接口,和toYamlString分开;
以下是错误格式:

在这里插入图片描述

3、代码改进

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

struct stat st;
/* 判断文件是否满了 */
if(!stat(m_filename.c_str(), &st)) {
if(st.st_size > m_file_buf) {    // 判断文件是否写满了
    m_filestream.close();	
    std::string newFile = m_filename.substr(0, m_filename.rfind('.'));
    int i;
//            /**方法一: 查看日志文件的修改文件的时间,哪个最旧,即替换哪个 */
//            /*uint64_t t = INT64_MAX;
//            int idx=0;
//            for(i=1; i<=backups_files ; ++i) {
//                std::string tmp = newFile + std::to_string(i) + ".txt";
//                if(!stat(tmp.c_str(), &st)) {
//                    idx = i;
//                    break;
//                }
//
//                if(((time(0) - st.st_mtime) / 24 * 60 * 60) > backups_days) {
//                    FSUtil::Rm(tmp);
//                    idx = i;
//                    break;
//                }
//                if(t >= st.st_mtime){
//                    t = st.st_mtime;
//                    idx=i;
//                    newFile = tmp;
//                }
//            }
//            FSUtil::Mv(m_filename, newFile);
//            FSUtil::Rm(m_filename);
//    		  FSUtil::OpenForWrite(m_filestream, m_filename.c_str(), std::ios::app);
//            */
//
    /** 方法二:根据记录 */
    for(i=1; i<=m_backups_files ; ++i) {
        std::string tmp = newFile + std::to_string(i) + ".txt";
        if(stat(tmp.c_str(), &st)) {   // 判断文件是否存在
            break;
        }
        /* 判断日志是否过期 */
        if(((time(0) - st.st_mtime) / (24 * 60 * 60)) > m_backups_days) {
            FSUtil::Rm(tmp);
        }
    }
    FSUtil::Mv(m_filename, newFile+std::to_string(m_file_num) + ".txt");
    FSUtil::Rm(m_filename);

    FSUtil::OpenForWrite(m_filestream, m_filename.c_str(), std::ios::app);
    m_file_num += 1;
    if(m_file_num > m_backups_files) m_file_num = 1;
    IsChange = true;	// 若为true则需要更新yaml配置文件
}  

4、测试

测试循环覆盖写文件

此时的配置文件为:

在这里插入图片描述

测试代码

#include <iostream>
#include "../sylar/log.h"
#include "../sylar/util.h"
#include "../sylar/config.h"
#include <unistd.h>

#include <time.h>

int main(int argc, char** argv) {

    sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("root");

    sylar::Config::LoadFromYaml("/root/code/log_server/bin/conf/log.yml");
    // 输出日志
    std::cout << g_logger->toYamlString() << std::endl;
    for(int i=0; i<160000; ++i) {
        SYLAR_LOG_INFO(g_logger) << i;
        sleep(1);
    }

    return 0;
}

在这里插入图片描述
在这里插入图片描述

参考文章

=========》Log4j2 RollingFileAppender《=========
=========》滚动文件附加器指南《=========
=========》RollingFileWithCleanupAppender《=========

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jxiepc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值