需求分析
- 日志模块: 收集记录各级别下系统运行信息, 包括事件、运行情况、错误。
- 输出模块: 实现类printf式的格式输出。
- 设备管理模块: 能够模拟虚拟设备并实现与系统的交互接口。
- 文件系统管理: 实现对文件系统的操作、维护。
- 图形化窗口: 实现对系统状态的捕捉和图形化展示。
实现设计
日志模块
- C++实现,模仿Linux系统日志模块。
- 采用debug、info、notice、warning、error、critical、alert、emergency 8个级别日志等级对日志优先级进行分类。
- 设计系统日志api,创建日志守护进程来获取系统及应用的日志信息。
- 通过日志旋转来实现对日志的单个日志的定期清理,通过脚本来实现对所有日志的定期清理。
- 通过脚本实现对日志的定期备份从而在需要时实现日志回滚。
输出模块
- C++实现,模仿printf函数。
- 提供不同的格式说明符,包括一些输出需要的系统变量。
- 实现输出到定义接口的功能。
设备管理模块
- C++实现。
- 通过类实现一个设备管理器,提供设备注册机制和设备间通信
- 使用文件来模拟设备的数据储存。
文件系统管理
- C++实现,模仿Linux文件系统管理。
- 实现对文件的CRUD,文件的权限、所有权等功能。
图形化窗口
- C++实现,使用QT框架。
- 通过与其他模块的接口捕捉系统状态,并对系统状态图形化展示。
实现
日志&输出
类详解
LogLevel类描述
LogLevel 类定义了日志系统中使用的日志级别。这个类使用枚举类型表示不同的日志级别,从而方便日志的分类和过滤。每个级别代表了日志信息的重要性和紧急程度,从调试信息到致命错误。
属性
Level:枚举类型,定义了各种可能的日志级别。包括:
- UNKNOW:未知级别,通常用于初始化或错误处理。
- DEBUG:调试级别,用于详细的系统调试信息。
- INFO:信息级别,用于常规的操作信息。
- WARN:警告级别,表示可能的问题,但不一定影响系统运行。
- ERROR:错误级别,表示发生了影响操作的问题。
- FATAL:致命级别,表示严重的问题,可能导致系统停止运行。
方法
静态方法,用于将日志级别枚举转换为相应的字符串表示。这个方法通过一个switch语句实现,对应每个枚举值返回一个固定的字符串。例如,DEBUG级别返回"DEBUG"字符串,这对于日志输出和调试非常有用。
- FromString(const std::string& str)
静态方法,用于将字符串转换回相应的日志级别枚举。此方法通常通过一系列的 if 或 else if 语句实现,对比输入字符串与各日志级别名称,返回匹配的枚举值。如果没有找到匹配项,通常返回 UNKNOW。
使用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
| std::string levelStr = LogLevel::ToString(LogLevel::DEBUG); std::cout << "Log level is: " << levelStr << std::endl;
LogLevel::Level level = LogLevel::FromString("DEBUG"); std::cout << "Converted log level from string is: " << static_cast<int>(level) << std::endl;
```
##### LogEvent类描述
LogEvent 类是一个封装了单个日志事件的详细信息的类,用于在日志系统中表示一个具体的日志记录点。这个类包含了日志发生时的各种环境信息,如时间、文件名、行号以及线程和协程的标识,使得每条日志能够提供足够的上下文信息。
###### 属性
- logger:关联的 Logger 对象的智能指针,表示产生此日志事件的日志器。 - level:日志级别,由 LogLevel::Level 枚举表示。 - file:生成日志事件的源文件名。 - line:生成日志事件的行号。 - elapse:程序启动后到日志事件创建时的毫秒数。 - threadId:生成日志的线程ID。 - fiberId:生成日志的协程ID(如果使用协程)。 - time:日志事件生成的时间戳。 - threadName:生成日志的线程名称。 - ss:一个字符串流,用于收集日志信息。
###### 方法
- LogEvent
> 构造函数,初始化所有的日志相关信息。它接收与属性对应的参数,并将它们存储在类的成员变量中。
- getFile()
> 返回日志事件相关的文件名。
- getLine()
> 返回产生日志事件的代码行号。
- getTime()
> 返回日志事件的时间戳。
- getThreadId()
> 返回生成日志的线程ID。
- getFiberId()
> 返回生成日志的协程ID。
- getElapsedTime()
> 返回自程序启动以来到日志事件发生时的时间差(毫秒)。
- getThreadName()
> 返回生成日志的线程名称。
- getLogger()
> 返回产生此日志事件的 Logger 对象的智能指针。
- getSS()
> 返回用于收集日志内容的字符串流。 - format(const char* fmt, ...)
> 格式化输出日志信息,可以接受格式化参数并写入到 ss。
###### 使用方法
```cpp Logger::ptr logger = std::make_shared<Logger>("example"); LogEvent::ptr event(new LogEvent( logger, LogLevel::INFO, __FILE__, __LINE__, 0, GetCurrentThreadId(), GetCurrentFiberId(), time(nullptr), "main_thread" )); event->getSS() << "This is a log message"; logger->log(LogLevel::INFO, event); ```
##### LogEventWrap类描述
LogEventWrap 类是一个用于自动管理日志事件生命周期的辅助类,主要功能是在其生命周期结束时自动完成日志的记录。该类封装了一个 LogEvent 对象,并在析构时确保日志事件被正确处理,这样可以减少在函数中显式调用日志记录的需要。
###### 属性
- m_event:LogEvent 对象的智能指针,存储实际的日志事件。
###### 方法
- LogEventWrap(LogEvent::ptr e)
> 构造函数,接收一个 LogEvent 的智能指针,并将其存储在成员变量 m_event 中。这个构造函数允许 LogEventWrap 对象在创建时就持有一个日志事件的引用。
- ~LogEventWrap()
> 析构函数,在 LogEventWrap 对象生命周期结束时被调用。它的主要作用是自动触发日志事件的处理,如将其内容写入到日志系统。这样设计可以确保即使在复杂的函数调用中也不会丢失日志记录。
- getEvent() const
> 返回存储在 m_event 中的 LogEvent 对象的智能指针。这允许外部访问封装的日志事件,可能用于进一步处理或查询。
- getSS()
> 返回与 m_event 关联的字符串流引用。这个方法通常用于向日志事件中添加具体的日志信息,例如通过 getSS() << "Some log message"; 的方式。
###### 使用方法
```cpp Logger::ptr logger = std::make_shared<Logger>("example"); LogEvent::ptr event(new LogEvent(logger, LogLevel::INFO, __FILE__, __LINE__, 0, GetCurrentThreadId(), 0, time(nullptr), "main_thread")); { LogEventWrap event_wrap(event); event_wrap.getSS() << "This is a log message."; }
|
LogFormatter 类是用于将 LogEvent 对象格式化为字符串的关键组件,以便日志可以被输出到各种媒介。该类通过一个定义明确的格式模板对日志事件进行结构化表示,该模板支持丰富的格式化指令来包含或排除日志内容的特定部分。
属性
- m_pattern:字符串,保存日志格式化模板。
- m_items:FormatItem 对象的列表,每个对象代表模板中的一个格式化指令。
- m_error:布尔值,表示在格式化过程中是否遇到错误。
方法
- LogFormatter(const std::string& pattern)
构造函数,接收一个格式化模板字符串并初始化 m_pattern。构造时还会调用 init() 方法来解析模板并构建 m_items。
- format(std::shared_ptr logger, LogLevel::Level level, LogEvent::ptr event)
将 LogEvent 对象格式化为字符串。这个方法遍历 m_items,使用每个 FormatItem 对象来转换日志事件的相应部分。
- format(std::ostream& ofs, std::shared_ptr logger, LogLevel::Level level, LogEvent::ptr event)
类似于上一个 format 方法,但这里的输出是写入到一个输出流中,使其可以直接输出到文件或控制台。
解析 m_pattern 字符串,并根据解析结果创建相应的 FormatItem 对象填充到 m_items。这个方法处理模板中的各种格式化指令,并对应生成处理这些指令的 FormatItem 对象。
返回一个布尔值,表示格式化过程中是否有错误发生。
返回格式化模板字符串。
使用方法
std::string pattern = "%d