C++简单实现一个日志类

C++ 没有貌似自带的日志类,如果仅仅使用cout输出调试信息的话比较凌乱,所以我尝试自己实现了一个Logger类,主要考虑实现以下功能:

  • 日志等级: 参考python的logger类,我设置了四个日志等级, 从低到高依次为debug, info, warning, error,这样的话我想输出一条debug信息就可以这样写logger.debug("something..."), (关于日志等级是什么意思可以参考一下python的logger类,简单来说就是当日志等级大于等于设置的初始等级时才会记录日志)
  • 输出目标: 我设置了三种输出目标: 仅输出到终端、仅输出到文件、既输出到终端又输出到文件

为了方便的设置日志等级,可以用一个枚举类表示四种日志等级,同理用一个枚举类表示三种输出目标

enum log_level{debug, info, warning, error};// 日志等级
enum log_target{file, terminal, file_and_terminal};// 日志输出目标

为了更好地管理日志,我用一个类封装了日志工具,在构造函数中设定日志等级、输出目标、日志文件路径等,并提供DEBUG、INFO、WARNING、ERROR四个接口
对于日志内容还增加了一些前缀,比如使用__FILE__宏表示当前运行位置所在的文件,封装一个currTime()函数用以记录日志记录时间等

头文件:

# ifndef LOG_SYS_H
# define LOG_SYS_H

# include <iostream>
# include <fstream>
# include <string>
# include <time.h>
# include <stdio.h>
# include <stdlib.h>

using std::cout;
using std::string;
using std::endl;
using std::to_string;
using std::ios;

string currTime(){
    // 获取当前时间,并规范表示,
    // 这函数有点问题,有需要的话请自己改一下。。。
    // char tmp[64];
    // time_t ptime;
    // time(&ptime);  // time_t time (time_t* timer);
    // strftime(tmp, sizeof(tmp), "%Y-%m-%d %H:%M:%S", localtime(&ptime));
    // return tmp;
    return "2022-09-21 12:12:36\0"
}

class Logger{
public:
    enum log_level{debug, info, warning, error};// 日志等级
    enum log_target{file, terminal, file_and_terminal};// 日志输出目标
private:
    std::ofstream outfile;    // 将日志输出到文件的流对象
    log_target target;        // 日志输出目标
    string path;              // 日志文件路径
    log_level level;          // 日志等级
    void output(string text, log_level act_level);            // 输出行为
public:
    Logger();  // 默认构造函数
    Logger(log_target target, log_level level, string path);
    void DEBUG(string text);
    void INFO(string text);
    void WARNING(string text);
    void ERROR(string text);
};

# endif

cpp文件

# include "log_sys.h"

Logger::Logger(){
    // 默认构造函数
    this->target = terminal;
    this->level = debug;
    cout << "[WELCOME] " << __FILE__ << " " << currTime() << " : " << "=== Start logging ===" << endl;
}

Logger::Logger(log_target target, log_level level, string path){
        this->target = target;
        this->path = path;
        this->level = level;
        string tmp = "";  // 双引号下的常量不能直接相加,所以用一个string类型做转换
        string welcome_dialog = tmp + "[Welcome] " + __FILE__ + " " + currTime() + " : " + "=== Start logging ===\n";
        if (target != terminal){
            this->outfile.open(path, ios::out | ios::app);   // 打开输出文件
            this->outfile << welcome_dialog;
        }
        if (target != file){
            // 如果日志对象不是仅文件
            cout << welcome_dialog;
        }
    }

void Logger::output(string text, log_level act_level){
    string prefix;
    if(act_level == debug) prefix = "[DEBUG]   ";
    else if(act_level == info) prefix = "[INFO]    ";
    else if(act_level == warning) prefix = "[WARNING] ";
    else if(act_level == error) prefix = "[ERROR]   ";
    else prefix = "";
    prefix += __FILE__;
    prefix += " ";
    string output_content = prefix + currTime() + " : " + text + "\n";
    if(this->level <= act_level && this->target != file){
        // 当前等级设定的等级才会显示在终端,且不能是只文件模式
        cout << output_content;
    }
    if(this->target != terminal)
        outfile << output_content;
}


void Logger::DEBUG(string text){
    this->output(text, debug);
}

void Logger::INFO(string text){
    this->output(text, info);
}

void Logger::WARNING(string text){
    this->output(text, warning);
}

void Logger::ERROR(string text){
    this->output(text, error);
}

测试

void logger_test(){
    Logger logger(Logger::file_and_terminal, Logger::debug, "result.log");
    logger.DEBUG("What happend?");
    logger.INFO("This is good.");
    logger.WARNING("Yes...");
    logger.ERROR("IO Error!");
}

在这里插入图片描述

  • 17
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
状态连接防火墙的实现主要依赖于对网络数据包的解析和状态维护。以下是一个简单C++代码示例,用于演示如何实现状态连接防火墙: ```c++ #include <iostream> #include <unordered_map> #include <string> #include <vector> using namespace std; // 定义网络数据包结构体 struct Packet { string src_ip; string dest_ip; int src_port; int dest_port; string protocol; }; // 定义连接状态结构体 struct Connection { string src_ip; string dest_ip; int src_port; int dest_port; string protocol; int state; // 0表示未连接,1表示已连接 }; // 定义状态连接防火墙 class StatefulFirewall { public: // 添加规则 void add_rule(string src_ip, string dest_ip, int src_port, int dest_port, string protocol) { rules.push_back({src_ip, dest_ip, src_port, dest_port, protocol}); } // 处理数据包 bool process_packet(Packet packet) { // 判断数据包是否匹配某个规则 for (auto& rule : rules) { if (rule.src_ip == packet.src_ip && rule.dest_ip == packet.dest_ip && rule.src_port == packet.src_port && rule.dest_port == packet.dest_port && rule.protocol == packet.protocol) { // 如果匹配,则根据连接状态进行处理 ConnectionKey key = {packet.src_ip, packet.dest_ip, packet.src_port, packet.dest_port, packet.protocol}; if (connections.count(key) == 0) { // 如果连接不存在,则添加连接 connections[key] = {packet.src_ip, packet.dest_ip, packet.src_port, packet.dest_port, packet.protocol, 1}; return true; } else { // 如果连接已存在,则判断连接状态 Connection& conn = connections[key]; if (conn.state == 0) { // 如果连接未连接,则更新连接状态并返回true conn.state = 1; return true; } else { // 如果连接已连接,则返回false return false; } } } } // 如果数据包不匹配任何规则,则返回false return false; } private: // 定义连接键结构体 struct ConnectionKey { string src_ip; string dest_ip; int src_port; int dest_port; string protocol; bool operator==(const ConnectionKey& other) const { return src_ip == other.src_ip && dest_ip == other.dest_ip && src_port == other.src_port && dest_port == other.dest_port && protocol == other.protocol; } }; // 定义连接键的哈希函数 struct ConnectionKeyHash { size_t operator()(const ConnectionKey& key) const { return hash<string>()(key.src_ip) ^ hash<string>()(key.dest_ip) ^ hash<int>()(key.src_port) ^ hash<int>()(key.dest_port) ^ hash<string>()(key.protocol); } }; vector<Connection> connections; // 连接状态列表 unordered_map<ConnectionKey, Connection, ConnectionKeyHash> connections; // 连接状态哈希表 vector<Connection> rules; // 规则列表 }; int main() { // 创建状态连接防火墙对象 StatefulFirewall firewall; // 添加规则 firewall.add_rule("192.168.1.100", "192.168.2.100", 80, 8080, "tcp"); firewall.add_rule("192.168.1.100", "192.168.2.100", 443, 8443, "tcp"); // 处理数据包 Packet packet1 = {"192.168.1.100", "192.168.2.100", 80, 8080, "tcp"}; bool result1 = firewall.process_packet(packet1); cout << "packet1 result: " << result1 << endl; Packet packet2 = {"192.168.1.100", "192.168.2.100", 80, 8080, "tcp"}; bool result2 = firewall.process_packet(packet2); cout << "packet2 result: " << result2 << endl; Packet packet3 = {"192.168.1.100", "192.168.2.100", 443, 8443, "tcp"}; bool result3 = firewall.process_packet(packet3); cout << "packet3 result: " << result3 << endl; Packet packet4 = {"192.168.1.100", "192.168.2.100", 80, 8080, "udp"}; bool result4 = firewall.process_packet(packet4); cout << "packet4 result: " << result4 << endl; return 0; } ``` 在上面的代码中,我们定义了一个 `Packet` 结构体表示网络数据包,以及一个 `Connection` 结构体表示连接状态。同时,我们定义了一个 `StatefulFirewall` 表示状态连接防火墙,该包含两个成员变量:一个连接状态列表 `connections` 和一个规则列表 `rules`,以及两个成员函数:添加规则的 `add_rule` 和处理数据包的 `process_packet`。 在 `add_rule` 函数中,我们将规则添加到规则列表 `rules` 中。在 `process_packet` 函数中,我们首先遍历规则列表 `rules`,查找是否有规则与数据包匹配。如果有匹配的规则,则根据连接状态进行处理。我们使用一个哈希表 `connections` 来维护连接状态,哈希表的键是 `ConnectionKey` 结构体,哈希表的值是 `Connection` 结构体。在处理数据包时,我们首先根据数据包的源IP、目的IP、源端口、目的端口和协议构造出一个连接键 `key`,然后在哈希表中查找是否存在该连接。如果连接不存在,则添加连接并返回true;如果连接已存在,则根据连接状态进行处理。如果连接未连接,则更新连接状态并返回true;如果连接已连接,则返回false。 在上面的代码中,我们定义了一个简单的状态连接防火墙,仅支持规则匹配和连接状态维护,实际的防火墙还需要支持更多的功能,例如流量控制、攻击检测、日志记录等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值