sylar库学习-日志系统


前言

学习c++的过程中,伴随着迷茫,不知道如何使用特性,不知道如何将函数分类,不知道如何写代码和注释符合规范,以及软件工程中的UML绘图,功能如何拆分,系统调用的使用,工程是如何写出来的。在无人领路去自学这些的情况下,无疑是痛苦的。古人云,学而不思则罔,思而不学则殆。这些文章只是记录我所学的和我所思的,可能观点和方法会是错的,但闭门造车是更大的错误。希望能将我的学和思分享给大家,大家再根据自己的认识相互的交流,进一步的相互学习。在此过程中也能记录自己走过的路以慰未来的我。我现在会往Linux服务器编程的方向上去努力,现阶段目标暂定跟写
sylar,这个项目在b站上有视频,github上也有代码(虽然好像没有日志部分)但是能跟着别人的思路去写,有大佬告诉为什么这么写那就是已经是非常美好的事情了。
这是这位大佬项目的github地址

github: https://github.com/sylar-yin/sylar

我自己跟写的完整日志器代码整理地址

https://blog.csdn.net/m0_55292629/article/details/125262528

一、安装环境

环境是随时间随想做的方向不断变化的,虽然视频中所说的环境使用的是centos,但是我还是暂时使用的ubuntu20.04-servers-amd64版本。(原因centos可能过段时间会停止维护,而使用服务器版本的原因是使用桌面版放久了容易卡死不动),我所下载地址:

中科大源 :http://mirrors.ustc.edu.cn/ubuntu-releases

预先善其事,必先利其器
初级阶段暂时只要安装以下环境
gcc 和 cmake 安装

sudo apt-get install cmake
sudo apt install build-essential

若是没有网的话,可以使用命令配置网络信息

sudo vi /etc/network/interfaces

方法一
至于编程IDE可以选择选择使用visual studio 2019远程编程参考文章如下

https://blog.csdn.net/qq_41683305/article/details/122386148

其中碰到了无法导入linux内系统库的问题直接导致了无法代码补全,包含头文件报错。
具体的解决思路是将linux本地的包
/user/include
/usr/local/include
直接打包然后再复制到项目文件夹内。再从本地调用思路类似于

https://blog.csdn.net/qq_34950682/article/details/107323887?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-107323887-blog-116646073.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-107323887-blog-116646073.pc_relevant_default&utm_relevant_index=2

在此操作不同的是可以使用filezilla软件直接找到前面说的文件夹将内容复制到想要的位置。
具体过程为在visual studio内
项目->属性->C/C+±>常规
用分号隔开虽然我是将这些包复制到了项目内,但是这里我觉得可以专门开辟一个单独的文件夹用来存放和同步linux库头文件。可以用来防止有多个linux项目时需要备份多次的情况。
方法二
或者选择使用vim,上面提到的项目好像使用的就是经过拓张的vim,对此也进行了研究,一般使用的插件为YouCompleteMe。
前提需要git cmke Vundle python3等具体的安装可以直接去github上面找,下面提供github地址和插件的安装教程

https://github.com/ycm-core/YouCompleteMe

但是ubuntu好像只需要两行代码配置

sudo apt install vim-youcompleteme
vim-addons install youcompleteme

其中可能会碰到"NoExtraConfDetected"问题可以参考下面这篇文章

https://blog.csdn.net/u014070086/article/details/88692896

方法三
vscode 远程连接服务器方式

https://blog.csdn.net/mikudouble/article/details/120071377

其中还需要增加一个terminal插件,对于c/c++的插件也可以换成clangd插件(clangd插件好使一些不管是打开速度还是代码补全方面都好一些,c/c++总是容易卡)但是不要两个插件同时开,就可以直接在windows平台上操作Linux服务器,论实现来说,这个vscode最省心省力,代码补全啥的也都有,因此本人使用的是vscode搭配插件的方式来进行跟写的。

二、正式跟写

1.日志部分

日志部分最主要的类是日志器,事件器,和输出器,并且是以一个namespace来进行的描述的,所有日志有关的类写在了一个文件里(log.h,log.cc),里面大量使用了shared_ptr指针,大致关系结构如下
其中ptr是shared_ptr的智能指针

其中分工大致为

  • LogEvent是存放信息的地方,包括行、列、线程号、协程号、内容等
  • LogFormatter是安排数据摆放顺序,包含模式解析等功能(可以看看log4j标准)
  • LogAppender是输出地,可以选择文件或控制台进行输出,里面也包含了LogFormatter对象,来保证不同的输出地可以以不同的格式呈现
  • Logger是日志器,作为控制中枢可以将同一个信息添加多个LogAppender和LogFormatter对象来保证可以同时往多个地方输出
    在这里插入图片描述

LogEvent

class LogEvent {
   
public:
    typedef std::shared_ptr<LogEvent> ptr;
    LogEvent(std::shared_ptr<Logger> logger,LogLevel::Level level,const char *file, int32_t line, uint32_t elapse, uint32_t thread_id, uint32_t fiber_id, uint64_t time);
    const char *getFile() const {
    return m_file; }
    int32_t getLine() const {
    return m_line; }
    uint32_t getElapse() const {
    return m_elapse; }
    uint32_t getThreadId() const {
    return m_threadId; }
    uint32_t getFiberId() const {
    return m_fiberId; }
    uint64_t getTime() const {
    return m_time; }
    std::string getContent() const {
    return m_ss.str(); }
    std::stringstream &getSS() {
    return m_ss; }
    std::shared_ptr<Logger> getLogger()const{
   return m_logger;}
    LogLevel::Level getLevel() const {
    return m_level; }
    void format(const char *fmt, ...);
    void format(const char *fmt,va_list al);

private:
    
    const char *m_file = nullptr; //文件名
    int32_t m_line = 0;           // 行号
    uint32_t m_elapse = 0;        //程序启动开始到现在的毫秒数
    uint32_t m_threadId = 0;      //线程id
    uint32_t m_fiberId = 0;       //协程
    uint32_t m_time = 0;          //时间戳
    std::stringstream m_ss;
    std::shared_ptr<Logger> m_logger;
    LogLevel::Level m_level;
};
void LogEvent::format(const char *fmt, ...) {
   //经典C字符串处理方式
  va_list al;
  va_start(al, fmt);
  format(fmt, al);
  va_end(al);
}
void LogEvent::format(const char *fmt, va_list al) {
   
  char *buf = nullptr;
  int len = vasprintf(&buf, fmt, al);
  if (len != -1) {
   
    m_ss << std::string(buf, len);
    free(buf);
  }
}
LogEvent::LogEvent(std::shared_ptr<Logger> logger, LogLevel::Level level,
                   const char *file, int32_t line, uint32_t elapse,
                   uint32_t thread_id, uint32_t fiber_id, uint64_t time)
    : m_file(file), m_line(line), m_elapse(elapse), m_threadId(thread_id),
      m_fiberId(fiber_id), m_time(time),m_logger(logger),m_level(level)
      {
   
}

此类相当于一个日志消息的数据库,函数也主要是获得类内的信息,并且保存起来。

sylar::LogEvent::ptr(new sylar::LogEvent(                                
          logger, level, __FILE__, __LINE__, 0, sylar::GetThreadId(),          
          sylar::GetFiberId(), time(0))))
   //使用智能指针进行初始化,也是信息的初始化
	//控制器、行号、信息等级、文件名、行号、获取线程号、协程号、已运行时间,可以通过各种函数和宏去实现

LogFormatter类主要是根据pattern字符串安排各个信息排列的顺序以及附加其他的信息(此处可以看log4j格式)。信息是拼接起来的,其中使用了字符串流进行拼接。解析pattern字符串后按照解析顺序将信息存放到有序数组里。使用的时候将这些信息一一打印出来。

class LogFormatter{
   
public:
    typedef std::shared_ptr<LogFormatter> ptr;
    LogFormatter(const std::string &pattern);
    std::string format(std
  • 8
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值