当前位置: 首页 > news >正文

C++项目实战——基于多设计模式下的同步异步日志系统-⑫-日志宏全局接口设计(代理模式)

文章目录

  • 专栏导读
  • 日志宏&全局接口设计
  • 全局接口测试
  • 项目目录结构整理
  • 示例代码
    • 拓展示例代码

专栏导读

🌸作者简介:花想云 ,在读本科生一枚,C/C++领域新星创作者,新星计划导师,阿里云专家博主,CSDN内容合伙人…致力于 C/C++、Linux 学习。

🌸专栏简介:本文收录于 C++项目——基于多设计模式下的同步与异步日志系统

🌸相关专栏推荐:C语言初阶系列C语言进阶系列C++系列数据结构与算法Linux

在这里插入图片描述

日志宏&全局接口设计

本章我们将完成提供全局接口&宏函数,对日志系统接口进行使用便捷性优化(避免用户自己创建单例)。

设计思想:

  • 提供获取指定日志器的全局接口(避免用户自己操作单例对象);
  • 使用宏函数对日志器的接口进行代理(代理模式);
  • 提供宏函数,直接通过默认日志器进行日志的标准输出打印(省去获取日志器的操作);
#ifndef __MY_LOG__
#define __MY_LOG__
#include "logger.hpp"namespace LOG
{// 1.提供获取指定日志器的全局接口(避免用户自己操作单例对象)Logger::ptr getLogger(const std::string &name){return LOG::LoggerManager::getInstance().getLogger(name);}Logger::ptr rootLogger(){return LOG::LoggerManager::getInstance().rootLogger();}// 2.实用宏函数对日志器的接口进行代理(代理模式)#define debug(fmt, ...) debug(__FILE__, __LINE__, fmt, ##__VA_ARGS__)#define info(fmt, ...) info(__FILE__, __LINE__, fmt, ##__VA_ARGS__)#define warn(fmt, ...) warn(__FILE__, __LINE__, fmt, ##__VA_ARGS__)#define error(fmt, ...) error(__FILE__, __LINE__, fmt, ##__VA_ARGS__)#define fatal(fmt, ...) fatal(__FILE__, __LINE__, fmt, ##__VA_ARGS__)// 3.提供宏函数,直接通过默认日志器进行日志的标准输出打印#define DEBUG(fmt, ...) LOG::rootLogger()->debug(fmt, ##__VA_ARGS__)#define INFO(fmt, ...) LOG::rootLogger()->info(fmt, ##__VA_ARGS__)#define WARN(fmt, ...) LOG::rootLogger()->warn(fmt, ##__VA_ARGS__)#define ERROR(fmt, ...) LOG::rootLogger()->error(fmt, ##__VA_ARGS__)#define FATAL(fmt, ...) LOG::rootLogger()->fatal(fmt, ##__VA_ARGS__)}
#endif

全局接口测试

测试代码

void log_test()
{DEBUG("%s", "测试日志");INFO("%s", "测试日志");WARN("%s", "测试日志");ERROR("%s", "测试日志");FATAL("%s", "测试日志");size_t count = 0;while(count < 300000){FATAL("测试日志-%d", count++);}
}
int main()
{log_test();return 0;
}

项目目录结构整理

在这里插入图片描述

示例代码

// example/test.cc
#include "../logs/log.h"
#include <unistd.h>void log_test(const std::string& name)
{INFO("%s", "测试开始");LOG::Logger::ptr logger = LOG::LoggerManager::getInstance().getLogger("async_logger");logger->debug(__FILE__, __LINE__, "%s", "测试日志");logger->info(__FILE__, __LINE__, "%s", "测试日志");logger->warn(__FILE__, __LINE__, "%s", "测试日志");logger->error(__FILE__, __LINE__, "%s", "测试日志");logger->fatal(__FILE__, __LINE__, "%s", "测试日志");INFO("%s", "测试完毕");
}
int main()
{std::unique_ptr<LOG::LoggerBuilder> builder(new LOG::GlobalLoggerBuilder());builder->buildLoggerName("async_logger");builder->buildLoggerLevel(LOG::LogLevel::value::WARN);builder->buildFormatter("[%c][%f:%l]%m%n");builder->buildLoggerType(LOG::LoggerType::LOGGER_ASYNC);builder->buildSink<LOG::FileSink>("./logfile/async.log");builder->buildSink<LOG::StdOutSink>();builder->buildSink<LOG::RollBySizeSink>("./logfile/roll-async-by-size", 1024 * 1024);builder->build();log_test("async_logger");return 0;
}

拓展示例代码

// extent/test.cc
#include "../logs/log.h"
#include <unistd.h>enum class TimeGap
{GAP_SECOND,GAP_MINUTE,GAP_HOUR,GAP_DAY
};
class RollByTimeSink : public LOG::LogSink
{
public:// 构造时传入文件名,并打开文件,将操作句柄管理起来RollByTimeSink(const std::string &basename, TimeGap gap_type) : _basename(basename){switch(gap_type){case TimeGap::GAP_SECOND: _gap_size = 1; break;case TimeGap::GAP_MINUTE: _gap_size = 60; break;case TimeGap::GAP_HOUR: _gap_size = 3600; break;case TimeGap::GAP_DAY: _gap_size = 3600 * 24; break;}_cur_gap = _gap_size == 1? LOG::util::Date::getTime() : LOG::util::Date::getTime() % _gap_size; // 获取当前是第几个时间段std::string filename = createNewFile();LOG::util::File::createDirectory(LOG::util::File::path(filename));_ofs.open(filename, std::ios::binary | std::ios::app);assert(_ofs.is_open());}// 将日志消息写入到标准输出,判断当前时间是否是当前文件的时间段,不是则切换文件void log(const char* data, size_t len){time_t cur = LOG::util::Date::getTime();if((cur % _gap_size) != _cur_gap){_ofs.close();std::string filename = createNewFile();_ofs.open(filename, std::ios::binary | std::ios::app);assert(_ofs.is_open());}_ofs.write(data, len);assert(_ofs.good());}
private:std::string createNewFile(){time_t t = LOG::util::Date::getTime();struct tm lt;localtime_r(&t, &lt);std::stringstream filename;filename << _basename;filename << lt.tm_year + 1900;filename << lt.tm_mon + 1;filename << lt.tm_mday;filename << lt.tm_hour;filename << lt.tm_min;filename << lt.tm_sec;filename << "-";filename << ".log";return filename.str();}
private:std::string _basename;size_t _gap_size; // 时间段的大小int _cur_gap; // 当前是第几个时间段std::ofstream _ofs;
};int main()
{std::unique_ptr<LOG::LoggerBuilder> builder(new LOG::GlobalLoggerBuilder());builder->buildLoggerName("async_logger");builder->buildLoggerLevel(LOG::LogLevel::value::WARN);builder->buildFormatter("[%c][%f:%l]%m%n");builder->buildLoggerType(LOG::LoggerType::LOGGER_ASYNC);builder->buildSink<LOG::FileSink>("./logfile/async.log");builder->buildSink<LOG::StdOutSink>();builder->buildSink<RollByTimeSink>("./logfile/roll-async-by-time", TimeGap::GAP_SECOND);LOG::Logger::ptr logger = builder->build();size_t cur = LOG::util::Date::getTime();while(LOG::util::Date::getTime() < cur + 5){logger->fatal("这是一条测试日志");}return 0;
}

在这里插入图片描述

http://www.lryc.cn/news/197662.html

相关文章:

  • 京东数据接口:京东数据分析怎么做?
  • 使用Git在本地创建一个仓库并将其推送到GitHub
  • 5.覆盖增强技术——PUCCHPUSCH
  • 徐建鸿:深耕中医康养的“托钵行者”
  • 基于svg+js实现简单动态时钟
  • 端到端测试(End-to-end tests)重试策略
  • 三相交错LLC软启动控制驱动波形分析--死区时间与占空比关系
  • 数据结构详细笔记——栈与队列
  • JVM调试命令与调试工具
  • 《软件方法》第1章2023版连载(07)UML的历史和现状
  • chromium 54 chrome 各个版本发布功能列表(109-119)
  • Linux实现原理 — I/O 处理流程与优化手段
  • 第 367 场 LeetCode 周赛题解
  • 最新百度统计配置图文教程,获取siteId、百度统计AccessToken、百度统计代码教程
  • 【C++ 学习 ㉘】- 详解 C++11 的列表初始化
  • OpenCV12-图像卷积
  • MVCC与BufferPool缓存机制
  • POI、Easy Excel操作Excel
  • 网络安全(黑客)自学方向
  • react写一个简单的3d滚轮picker组件
  • Compose竖向列表LazyColumn
  • 6.自定义相机控制器
  • 一文带你GO语言入门
  • 前后端小项目链接
  • 编辑器功能:用一个快捷键来【锁定】或【解开】Inspector面板
  • Vue 网络处理 - axios 异步请求的使用,请求响应拦截器(最佳实践)
  • 关于W5500网卡使用过程的部分问题记录
  • Unity DOTS World Entity ArchType Component EntityManager System概述
  • 最详细STM32,cubeMX 点亮 led
  • 论文阅读:Image-to-Lidar Self-Supervised Distillation for Autonomous Driving Data