【封装一个日志库(linux)】【转载】

原文链接:

工具库1:封装一个日志库(linux)-CSDN博客

一、,需求

(1)封装一个c/c++日志库,提供格式打印接口,编写程序代码时方便使用;

(2) 格式打印接口支持可变参数;

(3)格式打印接口封装成可变参数宏,便于使用;

二,实现

(1)提供格式打印接口;

(2)日志等级分成三个级别,分别是错误、警告、普通信息;

(3)支持输出到终端,同时支持输出到指定日志文件;

(4)格式打印接口支持可变参数;

(5)打印字符串长度无限制;

三,源码

(1)messages.h

复制代码
/**
*****************************************************************************
*  Copyright (C), 2023-2024
*
*  @file    messages.h
*  @brief   printf pretty
*
*
*  @author  sbinhuang
*  @date    2023-06-28
*  @version v1.0.0 20230628
*----------------------------------------------------------------------------
*  @note 历史版本   修改人员    修改日期      修改内容
*  @note v1.0    sbinhuang   2023-06-28   1.创建
*
*****************************************************************************
*/
#ifndef _SELF_UTILITY_MESSAGES_H_
#define _SELF_UTILITY_MESSAGES_H_
#include <iostream>
#include <fstream>

namespace SelfUtility {
// message type
enum MessageType {
    NONE  = 0,
    ERROR = 1,
    WARN  = 2,
    INFO  = 3
};

class Messages {
 public:
    // default close file and enable terminal output
    static bool Init();
    // open log file
    // mode = true, open or create file and clear file content
    // mode = false, open or create file, doesn't clear file content
    static bool OpenLogFile(const char *file_name, bool mode = 0);
    // close log file
    static bool CloseLogFile();
    // enable terminal output
    static bool EnableTerminalOutput();
    // disable terminal output
    static bool DisableTerminalOutput();
    // print message for variable argument
    static bool Message(const MessageType &type, const char *file_name,
        int line_number, const char *format, ...);
    // print message for determine argument
    static bool Message(const MessageType &type, const char *file_name,
        int line_number, const char *format);

 private:
    static std::ofstream _os;
    static bool _terminal_output;
    static bool _write_file;
};

}  // namespace SelfUtility

#define LOG_ERROR(format, ...) do { \
    SelfUtility::Messages::Message(SelfUtility::MessageType::ERROR, \
                          __FILE__, __LINE__, format, __VA_ARGS__); \
} while (0)

#define LOG_WARN(format, ...) do { \
    SelfUtility::Messages::Message(SelfUtility::MessageType::WARN, \
                         __FILE__, __LINE__, format, __VA_ARGS__); \
} while (0)

#define LOG_INFO(format, ...) do { \
    SelfUtility::Messages::Message(SelfUtility::MessageType::INFO, \
                         __FILE__, __LINE__, format, __VA_ARGS__); \
} while (0)

#define LOG_PRINT(format, ...) do { \
    SelfUtility::Messages::Message(SelfUtility::MessageType::NONE, \
                         __FILE__, __LINE__, format, __VA_ARGS__); \
} while (0)

#define LOG_INIT() do { \
    SelfUtility::Messages::Init(); \
} while (0)


#endif  // _SELF_UTILITY_MESSAGES_H_

(2) messages.cpp

复制代码
/**
*****************************************************************************
*  Copyright (C), 2023-2024
*
*  @file    messages.cpp
*  @brief   printf pretty
*
*
*  @author  sbinhuang
*  @date    2023-06-28
*  @version v1.0.0 20230628
*----------------------------------------------------------------------------
*  @note 历史版本   修改人员    修改日期      修改内容
*  @note v1.0    sbinhuang   2023-06-28   1.创建
*
*****************************************************************************
*/
#include "messages.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <iostream>
#include <fstream>
#include <string>

using SelfUtility::MessageType;
using SelfUtility::Messages;

// static variable define for class Messages
std::ofstream Messages::_os;
bool Messages::_write_file;
bool Messages::_terminal_output;

// initial log print, default output terminal
bool Messages::Init() {
    if (_os.is_open()) _os.close();
    _terminal_output = true;
    _write_file = false;
    return true;
}

// Open log file
// mode = true, open or create file and clear file content
// mode = false, open or create file, doesn't clear file content
bool Messages::OpenLogFile(const char *file_name, bool mode) {
    if (!file_name) {
        std::cout << "Log file name is null pointer!" << std::endl;
        return false;
    }

    // open file
    if (true == mode) {
        _os.open(file_name, std::ios::out);
    } else {
        _os.open(file_name, std::ios::app);
    }

    if (!_os.is_open()) {
        std::cout << "File open failed!" << "(" << file_name
                  << ")" << std::endl;
        return false;
    }

    _write_file = true;
    return true;
}

// close log file
bool Messages::CloseLogFile() {
    if (_os.is_open()) _os.close();
    _write_file = false;
    return true;
}

// enable terminal output
bool Messages::EnableTerminalOutput() {
    _terminal_output = true;
    return true;
}

// disable terminal output
bool Messages::DisableTerminalOutput() {
    _terminal_output = false;
    return true;
}

// print message for variable argument
bool Messages::Message(const MessageType &type, const char *file_name,
    int line_number, const char *format, ...) {
    // print title
    if (MessageType::ERROR == type) {
        if (true == _terminal_output) {
            if (file_name) {
                std::cout << "[" << file_name << ": "
                    << line_number << "]";
            }
            std::cout << "ERROR: ";
        }

        if (true == _write_file) {
            if (file_name) {
                _os << "[" << file_name << ": "
                    << line_number << "]";
            }
            _os << "ERROR: ";
        }
    } else if (MessageType::WARN == type) {
        if (true == _terminal_output) {
            if (file_name) {
                std::cout << "[" << file_name << ": "
                    << line_number << "]";
            }
            std::cout << "WARN: ";
        }

        if (true == _write_file) {
            if (file_name) {
                _os << "[" << file_name << ": "
                    << line_number << "]";
            }
            _os << "WARN: ";
        }
    } else if (MessageType::INFO == type) {
        if (true == _terminal_output) std::cout << "INFO: ";
        if (true == _write_file) std::cout << "INFO: ";
    }

    // print message
    char *buf = NULL;
    va_list arg_ptr;
    va_start(arg_ptr, format);
    vasprintf(&buf, format, arg_ptr);
    va_end(arg_ptr);

    if (true == _terminal_output) {
        std::cout << buf;
    }

    if (true == _write_file) {
        _os << buf;
    }

    free(buf);
    buf = NULL;
    return true;
}

// print message for determine argument
bool Messages::Message(const MessageType &type, const char *file_name,
    int line_number, const char *format) {
    // print title
    if (MessageType::ERROR == type) {
        if (true == _terminal_output) {
            if (file_name) {
                std::cout << "[" << file_name << ": "
                    << line_number << "]";
            }
            std::cout << "ERROR: ";
        }

        if (true == _write_file) {
            if (file_name) {
                _os << "[" << file_name << ": "
                    << line_number << "]";
            }
            _os << "ERROR: ";
        }
    } else if (MessageType::WARN == type) {
        if (true == _terminal_output) {
            if (file_name) {
                std::cout << "[" << file_name << ": "
                    << line_number << "]";
            }
            std::cout << "WARN: ";
        }

        if (true == _write_file) {
            if (file_name) {
                _os << "[" << file_name << ": "
                    << line_number << "]";
            }
            _os << "WARN: ";
        }
    } else if (MessageType::INFO == type) {
        if (true == _terminal_output) std::cout << "INFO: ";
        if (true == _write_file) std::cout << "INFO: ";
    }

    // print message
    if (true == _terminal_output) std::cout << format;
    if (true == _write_file) _os << format;
    return true;
}
相关推荐
不会就选b1 小时前
数据结构之栈的算法题(OJ)
linux·数据结构·算法
刘某的Cloud1 小时前
k8s部署prometheus架构规则
linux·运维·kubernetes·prometheus·监控
mounter6251 小时前
从 2026 LSFMM/BPF 峰会看 eBPF 生态演进:技术变革、工具全景与资源泄漏诊断实战
linux·linux kernel·kernel
M78佐菲1 小时前
Linux学习笔记:网络通信
linux·笔记·学习·算法
AAA代码批发商2 小时前
Days37 Linux C 网络编程:UDP、TCP 与 HTTP 协议实战详解
linux·c语言·网络
好评1242 小时前
【Linux】传输层协议UDP
linux·运维·udp
GreatVicent2 小时前
AI Agent互操作标准化加速:A2A协议正式加入Linux基金会
linux·运维·人工智能·agent·aws·a2a
奇树谦3 小时前
Seaweed中filer.sync原理
linux·服务器·网络
Huangjin007_3 小时前
【Linux 系统篇(十六)】进程(四) : 僵尸进程、孤儿进程、进程优先级
linux·运维·服务器
瞬间&永恒~3 小时前
【Kubernetes】(十五)维护与升级、ETCD 备份和恢复
linux·运维·docker·云原生·kubernetes