MPRPC项目(第十天,日志功能实现)

一、日志功能

在本项目中,日志有以下功能

1、异步写入:使用独立线程写日志,不影响主业务逻辑性能

2、分级日志:区分INFO和ERROR级别,便于过滤和处理

3、按日期分文件:每天生成独立的日志文件,便于管理和查找

4、维护系统稳定性和排查问题

多个线程指需要使用日志记录的线程,

二、日志管理

1、logger.h

cpp 复制代码
#pragma once
#include "lockqueue.h"
#include<string>
enum LogLevel
{
    INFO,//普通信息
    ERROR,//错误信息
};

//Mprpc框架提供的日志系统
class Logger
{
public:
    //获取日志唯一的实例对象
    static Logger& GetInstance();    
    //设置日志级别
    void SetLogLevel(LogLevel level);
    //写日志
    void Log(std::string msg);
private:
    LogLevel m_loglevel;//记录日志级别
    LockQueue<std::string> m_lockQueue;//日志缓冲队列

    Logger();
    Logger(const Logger& other) = delete;
    Logger(Logger&&) = delete;
};

//定义宏
#define LOG_INFO(logmsgFormat, ...) \
    do \
    { \
        Logger& logger = Logger::GetInstance(); \
        logger.SetLogLevel(INFO); \
        char c[1024] = {0}; \
        snprintf(c, 1024, logmsgFormat, ##__VA_ARGS__); \
        logger.Log(c); \
    } while(0);

#define LOG_ERROR(logmsgFormat, ...) \
    do \
    { \
        Logger& logger = Logger::GetInstance(); \
        logger.SetLogLevel(ERROR); \
        char c[1024] = {0}; \
        snprintf(c, 1024, logmsgFormat, ##__VA_ARGS__); \
        logger.Log(c); \
    } while(0);

2、logger.cc

cpp 复制代码
#include"logger.h"
#include<iostream>
//获取日志唯一的实例对象
Logger& Logger::GetInstance(){
    static Logger logger;
    return logger;
}

Logger::Logger(){
    //启动专门的写日志线程
    std::thread writeLogTask([&](){
        for(;;){
            //获取当前日期,然后从队列获取日志信息,写入对应的日志文件中
            time_t now = time(NULL);
            tm* now_tm = localtime(&now);

            char file_name[128];
            sprintf(file_name, "%d-%d-%d.log.txt", now_tm->tm_year + 1900, now_tm->tm_mon + 1, now_tm->tm_mday);

            FILE* pf = fopen(file_name, "a+");
            if(pf == NULL){
                std::cout << "logger::open log file error" << std::endl;
                exit(EXIT_FAILURE);
            }

            std::string msg = m_lockQueue.Pop();
            char time_buf[128];
            sprintf(time_buf, "%d:%d:%d =>[%s]", now_tm->tm_hour, now_tm->tm_min, now_tm->tm_sec,
                                                 m_loglevel == INFO ? "INFO" : "ERROR");
            msg.insert(0, time_buf);    
            msg.append("\n");
            fputs(msg.c_str(), pf);
            fclose(pf);
        }
    });
    //设置分离线程,守护线程
    writeLogTask.detach();
}

//设置日志级别
void Logger::SetLogLevel(LogLevel level){
    m_loglevel = level;
}
//写日志
void Logger::Log(std::string msg){
    m_lockQueue.Push(msg);
}

三、异步日志队列

1、在MPRPC框架中的价值

  1. RPC调用性能:RPC服务的响应时间不会受日志写入影响(工作线程只需将日志消息放入队列即可继续执行业务逻辑,无需等待磁盘I/O)

  2. 高并发支持:多个客户端同时请求时,日志记录不会成为瓶颈

  3. 可靠性:即使日志文件系统出现问题,也不会影响RPC服务的正常运行

异步日志的唯一潜在缺点是在程序异常终止时可能丢失队列中的日志,但对于大多数应用场景,其性能优势远大于这个风险。

2、logqueue.h

这里使用条件变量,当队列为空时,日志线程调用wait,释放lock锁,让工作线程能写日志

cpp 复制代码
#pragma once
#include<queue>
#include<thread>
#include<mutex>
#include<condition_variable>

//异步写日志的日志队列
template<typename T>
class LockQueue{
public:
    //多个工作线程都会写日志
    void Push(const T& data){
        std::lock_guard<std::mutex> lock(m_mutex);
        m_queue.push(data);
        m_condvariable.notify_one();
    }

    //主线程会读取日志
    T Pop(){
        std::unique_lock<std::mutex> lock(m_mutex);
        while(m_queue.empty()){
            m_condvariable.wait(lock);
        }
        T data = m_queue.front();
        m_queue.pop();
        return data;
    }
private:
    std::queue<T> m_queue;
    std::mutex m_mutex;
    std::condition_variable m_condvariable;
};

四、应用例子

相关推荐
落羽的落羽20 分钟前
【AI】快速理解AI应用的相关名词概念
linux·c++·人工智能·python·计算机网络·算法
刚入门的大一新生22 分钟前
Linux-进程控制
linux·运维·服务器·c++
shmily麻瓜小菜鸡36 分钟前
JavaScript / TypeScript 易踩坑知识点 —— 异步编程类
开发语言·javascript·typescript
刃神太酷啦42 分钟前
Redis 进阶核心:持久化 (RDB/AOF)、事务与主从复制全解析----《Hello Redis!》(5)
linux·c语言·数据库·c++·redis·缓存·bootstrap
七夜zippoe1 小时前
为什么 2026 年每个 Java 团队都该懂 AI Agent
java·开发语言·人工智能
znnnk1 小时前
【Python】GUI 开发从入门到实战(三):PyQt/PySide 进阶之路
开发语言·python·pyqt
Despacito10061 小时前
Java后端性能探查工具速查表
java·开发语言
晊晌_h2 小时前
嵌入式从0到精通——Linux C|TCP 并发服务器实现方案详解
服务器·开发语言·tcp/ip
传奇开心果编程2 小时前
【Rust入门知识点学与练】第17课:闭包 Closures
开发语言·学习·rust
广州灵眸科技有限公司3 小时前
从手动三步到上电即连:4G模组systemd开机自连方案
linux·运维·服务器·开发语言·网络·人工智能·php