muduo网络库剖析——日志Log类

news2024/11/18 11:45:42

muduo网络库剖析——日志Log类

  • 前情
    • 从muduo到my_muduo
  • 概要
    • 日志
    • 日志级别
  • 框架与细节
    • 成员
    • 函数
  • 源码

前情

从muduo到my_muduo

作为一个宏大的、功能健全的muduo库,考虑的肯定是众多情况是否可以高效满足;而作为学习者,我们需要抽取其中的精华进行简要实现,这要求我们足够了解muduo库。

做项目 = 模仿 + 修改,不要担心自己学了也不会写怎么办,重要的是积累,学到了这些方法,如果下次在遇到通用需求的时候你能够回想起之前的解决方法就够了。送上一段话!

在这里插入图片描述

概要

日志

日志是用来记录重大事件的工具。
日志文件是重要的系统信息文件,其中记录了很多重要的系统事件。包括用户的登录信息,系统的启动信息,系统的安全信息,邮件相关信息,各种服务相关信息。
日志对于安全来说也很重要,它记录了每天系统发生的各种事情,通过日志来检查错误发生的原因,或者受到攻击时攻击者留下的痕迹。

日志级别

在这里插入图片描述
上面是muduo库的主要日志级别。
在这里插入图片描述
上面是我搜索到的日志级别解释。

框架与细节

成员

  1. 日志级别划分

    我们这里主要用到INFO、DEBUG、WARN、ERROR、FATAL作为我们小规模的日志库日志级别划分。

函数

  1. 日志级别设置

    在这里插入图片描述

    static修饰类成员函数则该成员函数属于整个类,而非类对象,调用需要加类域,初始化要在类外。

  2. 日志实例创建——单例模式

    我们通过返回静态变量能够获得唯一的日志实例,使用的是懒汉式单例模式。有关单例模式,想要了解复习的uu可以跳转到此。

  3. 写日志

    • 关于写日志,我们需要确定统一的写的格式,muduo库选择使用宏定义的方式来统一我们写单条日志的格式。
      在这里插入图片描述 这里使用到了是将宏定义做成流对象进行传输,类似于c++中的cout。我们同样可以使用类似于printf的格式类型来实现我们的日志输出格式化。比如:

       #define LOG_INFO(logmsgformat, ...)                             \
           do {                                                        \
               Log& lp = Log::getInstance();                           \
               lp.setLogLevel(INFO);                                   \
               char buf[64] = {0};                                     \
               snprintf(buf, sizeof buf, logmsgformat, ##__VA_ARGS__); \
               lp.writeLog(buf);                                       \
           } while (0)
       
       #define LOG_DEBUG(logmsgformat, ...)                            \
           do {                                                        \
               Log& lp = Log::getInstance();                           \
               lp.setLogLevel(DEBUG);                                  \
               char buf[64] = {0};                                     \
               snprintf(buf, sizeof buf, logmsgformat, ##__VA_ARGS__); \
               lp.writeLog(buf);                                       \
           } while (0)
       
       #define LOG_WARN(logmsgformat, ...)                             \
           do {                                                        \
               Log& lp = Log::getInstance();                           \
               lp.setLogLevel(WARN);                                   \
               char buf[64] = {0};                                     \
               snprintf(buf, sizeof buf, logmsgformat, ##__VA_ARGS__); \
               lp.writeLog(buf);                                       \
           } while (0)
       
       #define LOG_ERROR(logmsgformat, ...)                            \
           do {                                                        \
               Log& lp = Log::getInstance();                           \
               lp.setLogLevel(ERROR);                                  \
               char buf[64] = {0};                                     \
               snprintf(buf, sizeof buf, logmsgformat, ##__VA_ARGS__); \
               lp.writeLog(buf);                                       \
           } while (0)
       
       #define LOG_FATAL(logmsgformat, ...)                            \
           do {                                                        \
               Log& lp = Log::getInstance();                           \
               lp.setLogLevel(FATAL);                                  \
               char buf[64] = {0};                                     \
               snprintf(buf, sizeof buf, logmsgformat, ##__VA_ARGS__); \
               lp.writeLog(buf);                                       \
               exit(-1);                                               \
           } while (0)
      
    • VA_ARGS 是一个预处理宏,用于可变参数宏中。当你在一个宏定义中使用可变参数时,VA_ARGS 允许你捕获那些参数。它常用于宏定义的可变参数列表。

    • Log& lp = Log::getInstance();注意这行细节,我们使用引用可以避免赋值运算符。另外,我们也可以修改getInstance返回值,返回一个指针,这样也是可以实现功能的。

    • 因为FATAL定义为出现不可逆转的错误,所以采用程序结束的方式,exit(-1);

    • 对于writeLog函数的实现,我进行了规范的定义,[] : time, msg。输出结果应该如下:在这里插入图片描述
      后面将对时间功能进行重写。

    • 关于日志msg的格式输出,应该统一标准,至少需要达到这样的标准,才可以更好地在后期进行调试。
      在这里插入图片描述
      在此还要注意,buf的长度要大于我们输出的长度!!!

    源码

//Log.h
#pragma once 

#include <string>
#include <iostream>
#include <unistd.h>

#include "noncopyable.h"

enum LogLevel {
    INFO,
    ERROR,
    WARN,
    FATAL,
    DEBUG,
};

#define LOG_INFO(logmsgformat, ...)                             \
    do {                                                        \
        Log& lp = Log::getInstance();                           \
        lp.setLogLevel(INFO);                                   \
        char buf[128] = {0};                                     \
        snprintf(buf, sizeof buf, logmsgformat, ##__VA_ARGS__); \
        lp.writeLog(buf);                                       \
    } while (0)

#define LOG_DEBUG(logmsgformat, ...)                            \
    do {                                                        \
        Log& lp = Log::getInstance();                           \
        lp.setLogLevel(DEBUG);                                  \
        char buf[128] = {0};                                     \
        snprintf(buf, sizeof buf, logmsgformat, ##__VA_ARGS__); \
        lp.writeLog(buf);                                       \
    } while (0)

#define LOG_WARN(logmsgformat, ...)                             \
    do {                                                        \
        Log& lp = Log::getInstance();                           \
        lp.setLogLevel(WARN);                                   \
        char buf[128] = {0};                                     \
        snprintf(buf, sizeof buf, logmsgformat, ##__VA_ARGS__); \
        lp.writeLog(buf);                                       \
    } while (0)

#define LOG_ERROR(logmsgformat, ...)                            \
    do {                                                        \
        Log& lp = Log::getInstance();                           \
        lp.setLogLevel(ERROR);                                  \
        char buf[128] = {0};                                     \
        snprintf(buf, sizeof buf, logmsgformat, ##__VA_ARGS__); \
        lp.writeLog(buf);                                       \
    } while (0)

#define LOG_FATAL(logmsgformat, ...)                            \
    do {                                                        \
        Log& lp = Log::getInstance();                           \
        lp.setLogLevel(FATAL);                                  \
        char buf[128] = {0};                                     \
        snprintf(buf, sizeof buf, logmsgformat, ##__VA_ARGS__); \
        lp.writeLog(buf);                                       \
        exit(-1);                                               \
    } while (0)

class Log : noncopyable {
public:
    
    static Log& getInstance(); 
    void writeLog(const char* s);
    void setLogLevel(LogLevel logLevel) {
        logLevel_ = logLevel;
    }
private:
    //Log() {};
    LogLevel logLevel_;
    
};

//Log.cc
#include "Log.h"

Log& Log::getInstance() {
    static Log log;
    return log;
}


// [] : time, msg
void Log::writeLog(const char* s) {
    std::string ss;
    switch (logLevel_)
    {
    case INFO:
        ss += "[INFO] : ";
        break;
    case DEBUG:
        ss += "[DEBUG] : ";
        break;
    case ERROR:
        ss += "[ERROR] : ";
        break;
    case FATAL:
        ss += "[FATAL] : ";
        break;
    case WARN:
        ss += "[WARN] : ";
        break;
    default:
        break;
    }
    std::cout << ss << "time, " << s << std::endl;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1363095.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

freesurfer-reconall后批量提取TIV(颅内总体积)

#提取TIV #singleline=$(grep Estimated Total Intracranial Volume /usr/local/freesurfer/subjects/bect-3d+bold-wangjingchen-4.9y-2/stats/aseg.sta

开启Android学习之旅-4-Android集成FontAwesome

FontAwesome 是一个非常标准、统一风格的图标库。产品经理在原型中应用了很多图标都是FontAwesome。正常流程是 UI 需要再手工绘制或在 iconfont 或 iconpark 网站挨个找&#xff0c;如果在 Android 直接使用不是省了一步&#xff08;注意版权问题&#xff0c;使用免费版&#…

贯穿设计模式-责任链模式

样例代码 涉及到的项目样例代码均可以从https://github.com/WeiXiao-Hyy/Design-Patterns.git获取 需求 实时地&#xff0c;根据city&#xff0c;sex&#xff0c;product字段进行业务投放&#xff0c;比如&#xff1a;北京的男生&#xff1b;四川的电脑等等 → 责任链模式&…

dyld: Library not loaded: /usr/lib/swift/libswiftCoreGraphics.dylib

更新Xcode14后低版本iPhone调试报错 dyld: Library not loaded: /usr/lib/swift/libswiftCoreGraphics.dylib Referenced from: /var/containers/Bundle/Application/…/….app/… Reason: image not found 这是缺少libswiftCoreGraphics库 直接导入libswiftCoreGraphics库即…

国产手机的遮羞布又被撕,市占率仅3%,苹果才是真第一!

国产手机纷纷宣称自己击败了苹果&#xff0c;不过这些第一全部加了定语&#xff0c;例如某周销量&#xff0c;某个价格段等等&#xff0c;而日前一加中国区总裁李杰则揭开了这层遮羞布&#xff0c;就全年来看苹果才是中国手机市场第一名&#xff01; 李杰指出市调机构BCI给出的…

华为云服务器试用领取

系列文章目录 华为云服务器试用领取 领取的试用云服务器在哪 文章目录 系列文章目录介绍 介绍 我将会用该系列文章讲述如何在云服务器中安装大数据软件及其环境搭建。如有不足之处&#xff0c;还望指点。 本篇文章讲述的是华为云服务器的免费试用。 华为弹性云服务器 ECS 该云…

基于 IP 多播的网络会议程序(2024)

1.题目描述 局域网 IP 多播程序&#xff0c;设计一个图形界面的网络会议程序&#xff08;实现文本多播方式即可&#xff09;。 2.演示Demo 3.参考代码 广播发送代码 //服务端 #include <winsock2.h> #include <iostream> #include <list>#pragma comment(l…

滑动窗口协议仿真(2024)

1.题目描述 滑动窗口协议以基于分组的数据传输协议为特征&#xff0c;该协议适用于在数据链路层以及传输层中对按 顺序传送分组的可靠性要求较高的环境。在长管道传输过程&#xff08;特别是无线环境&#xff09;中&#xff0c;相应的滑动窗口 协议可实现高效的重传恢复。附录 …

Guava Cache 异步刷新技巧

前言 Guava Cache是一款非常优秀的本地缓存框架&#xff0c;提供简洁易用的 API 供开发者使用。 这篇文章&#xff0c;我们聊聊如何使用 Guava Cache 异步刷新技巧带飞系统性能 。 1 基本用法 首先&#xff0c;在 Java 应用中添加 maven 依赖&#xff1a; <dependency&g…

jsES6+新语法

目录 模板字符串标签模板字符串 函数增强默认值与解构剩余参数rest和arguments 箭头函数 展开语法SymbolSetSet方法weakSetweakSet常用方法 MapMap常用方法weakMapweakMap常用方法 PromiseProxy/Reflect迭代器与生成器ES6新增方法includes**Object.valuesObject.entriespadStar…

【SpringBoot】公共字段自动填充功能实现(枚举、自定义注解、AOP、反射)

1. 自定义注解 使用interface语法来定义注解&#xff08;Annotation&#xff09;。 注解的参数类似无参数方法&#xff0c;可以用default设定一个默认值&#xff0c;比如String value() default "";。 元注解&#xff1a;有一些注解可以修饰其他注解&#xff0c;这…

Diffusion扩散模型学习2:DDPM前向加噪过程torch实现

参考: https://arxiv.org/pdf/2006.11239.pdf ##论文 https://github.com/dtransposed/code_videos/blob/main/01_Diffusion_Models_Tutorial/Diffusion%20Model.ipynb ##code https://spaces.ac.cn/archives/9119 1、红色框: 前向过程论文公式推出可以从x0原图一步到最终噪声…

学习Redis缓存

学习Redis缓存 NoSQL和SQL的区别缓存缓存作用缓存成本添加Redis缓存 Redis特征Redis中数据结构Redis通用命令String类型Key的层级格式Hash类型Redis的Java客户端 NoSQL和SQL的区别 缓存 缓存就是数据交换的缓冲区&#xff0c;是存储数据的临时地方&#xff0c;一般读写性比较高…

数据分析——火车信息

任务目标 任务 1、整理火车发车信息数据&#xff0c;结果的表格形式为&#xff1a; 2、并输出最终的发车信息表 难点 1、多文件 一个文件夹&#xff0c;多个月的发车信息&#xff0c;一个excel&#xff0c;放一天的发车情况 2、数据表的格式特殊 如何分析表是一个难点 数…

洛谷 P1019 单词接龙

题目背景 注意&#xff1a;本题为上古 NOIP 原题&#xff0c;不保证存在靠谱的做法能通过该数据范围下的所有数据。 NOIP2000 提高组 T3 题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏&#xff0c;现在我们已知一组单词&#xff0c;且给定一个开头的字母&…

mysql视图和sql语句

mysql视图和sql语句 一.mysql视图1.数据的虚拟表示&#xff1a;2.简化复杂查询&#xff1a;3.安全性和权限控制&#xff1a;4.逻辑数据组织&#xff1a;5.更新限制&#xff1a;6.视图的创建&#xff1a; 二.mysq语句使用案列 MySQL的视图&#xff08;View&#xff09;是一个虚拟…

深入剖析pcap中的网络异常:TTL过期攻击、ARP中毒、TCP重传与重叠碎片等

网络流量数据包捕获是网络安全领域的重要部分&#xff0c;而pcap文件则是这一过程的常见载体。为了深入解析pcap文件中潜在的可疑网络流量&#xff0c;我们需要运用强大的网络安全威胁评估与审计工具。这些工具能够帮助我们捕捉、记录、检测和诊断网络中的数据传输问题&#xf…

c#调试程序一次启动两个工程(多个工程)

概述 c# - Visual Studio : debug multiple projects at the same time? 以在解决方案中设置多个启动项目(右键单击解决方案&#xff0c;转到设置启动项目&#xff0c;选择多个启动项目)&#xff0c;并为包含在解决方案(无、开始、不调试就开始)。如果您将多个项目设置为开始…

LeetCode 42:接雨水

一、题目描述 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1] 输出&#xff1a;6 解释&#xff1a;上面是由数组 [0,1,0,2,1,0,…

并发(3)

目录 11.Synchronized本质上是通过什么保证线程安全的&#xff1f; 12.Synchronized使得同时只有一个线程可以执行&#xff0c;性能比较差&#xff0c;有什么提升的方法&#xff1f; 13.Synchronized由什么样的缺陷&#xff1f;Java Lock是怎么弥补这些缺陷的&#xff1f; 1…