格式化器 (Formatter) 详解
Formatter 负责将 LogRecord 转换为可读的文本格式。
Formatter 概览
什么是 Formatter?
text
LogRecord (结构化数据)
↓
Formatter (格式化器)
↓
std::string (可读文本)
```bash
### 内置 Formatter
| Formatter | 特点 | 适用场景 |
|-----------|------|----------|
| DefaultFormatter | 只输出消息 | 最简单的需求 |
| AsciiColorFormatter | 带颜色、可配置 | 控制台输出 |
| FileFormatter | 纯文本、可配置 | 文件输出 |
## FormatterFlag 配置
FormatterFlag 控制输出中包含哪些组件。
### 可用标志
```cpp
enum FormatterFlag : uint32_t {
TIMESTAMP = 1 << 0, // 时间戳
LEVEL = 1 << 1, // 日志级别
TAG = 1 << 2, // 标签
THREAD_ID = 1 << 3, // 线程 ID
SOURCE_LOCATION = 1 << 4, // 源代码位置
MESSAGE = 1 << 5, // 消息内容
COLOR = 1 << 6, // ANSI 颜色
};
```text
### 预设组合
```cpp
// 最少:只有级别和消息
MINIMAL = LEVEL | MESSAGE
// 默认:时间戳、级别、标签、位置、消息
DEFAULT = TIMESTAMP | LEVEL | TAG | SOURCE_LOCATION | MESSAGE
// 详细:包含所有组件
VERBOSE = TIMESTAMP | LEVEL | TAG | THREAD_ID | SOURCE_LOCATION | MESSAGE
```bash
### 输出示例
| 标志组合 | 输出示例 |
|----------|----------|
| MINIMAL | `[INFO] Hello World` |
| DEFAULT | `[14:23:45] [INFO] [CFLog] main.cpp:42 Hello World` |
| VERBOSE | `[14:23:45] [INFO] [CFLog] [12345] main.cpp:42 Hello World` |
## AsciiColorFormatter
### 基本用法
```cpp
#include "cflog/formatter/console_formatter.h"
using namespace cf::log;
// 使用默认配置
auto formatter = std::make_shared<AsciiColorFormatter>();
```text
### 自定义配置
```cpp
// 最小输出
auto minimal = std::make_shared<AsciiColorFormatter>(
FormatterFlag::MINIMAL
);
// 详细输出(带颜色)
auto verbose = std::make_shared<AsciiColorFormatter>(
FormatterFlag::VERBOSE | FormatterFlag::COLOR
);
```text
### 运行时修改配置
```cpp
auto formatter = std::make_shared<AsciiColorFormatter>();
auto config = std::make_shared<FormatterConfig>();
// 禁用颜色
config->disable(FormatterFlag::COLOR);
// 启用线程 ID
config->enable(FormatterFlag::THREAD_ID);
// 自定义时间格式
config->set_timestamp_format("%Y-%m-%d %H:%M:%S");
formatter->set_config(config);
```bash
### ANSI 颜色映射
| 级别 | ANSI 代码 | 效果 |
|------|-----------|------|
| TRACE | `\033[96m` | 青色 |
| DEBUG | `\033[94m` | 蓝色 |
| INFO | `\033[92m` | 绿色 |
| WARNING | `\033[93m` | 黄色 |
| ERROR | `\033[91m` | 红色 |
### 输出示例
```text
[14:23:45] [INFO] [CFLog] 应用启动
^^^^^^ 绿色
[14:23:46] [WARNING] [Config] 配置文件未找到
^^^^^^^ 黄色
[14:23:47] [ERROR] [Network] 连接失败
^^^^^ 红色
```text
## FileFormatter
### 基本用法
```cpp
#include "cflog/formatter/file_formatter.h"
using namespace cf::log;
auto formatter = std::make_shared<FileFormatter>();
```text
### 特点
FileFormatter 与 AsciiColorFormatter 基本相同,但:
- **忽略 COLOR 标志**:文件中不包含 ANSI 转义码
- 适合日志文件持久化
```cpp
// 即便设置了 COLOR,FileFormatter 也不会输出颜色代码
auto formatter = std::make_shared<FileFormatter>(
FormatterFlag::DEFAULT | FormatterFlag::COLOR // COLOR 被忽略
);
```text
## DefaultFormatter
### 特点
最简单的 Formatter,只输出消息内容。
```cpp
#include "cflog/formatter/default_formatter.h"
auto formatter = std::make_shared<DefaultFormatter>();
```text
**输出**:只包含 `LogRecord.msg`
**不可配置**:`configurable()` 返回 `false`
## FormatterConfig
### 创建配置
```cpp
#include "cflog/cflog_format_config.h"
// 默认配置
auto config = std::make_shared<FormatterConfig>();
// 自定义配置
auto config = std::make_shared<FormatterConfig>(
FormatterFlag::MINIMAL,
"%H:%M:%S" // 时间格式
);
```text
### 线程安全操作
```cpp
// 启用组件
config->enable(FormatterFlag::THREAD_ID);
// 禁用组件
config->disable(FormatterFlag::SOURCE_LOCATION);
// 检查是否启用
if (config->is_enabled(FormatterFlag::COLOR)) {
// ...
}
// 设置所有标志
config->set_flags(FormatterFlag::VERBOSE);
```bash
### 时间戳格式
使用 `strftime` 格式字符串:
| 格式 | 输出示例 | 说明 |
|------|----------|------|
| `"%H:%M:%S"` | `14:23:45` | 时:分:秒(默认) |
| `"%Y-%m-%d %H:%M:%S"` | `2026-03-16 14:23:45` | 完整日期时间 |
| `"%m/%d %H:%M:%S"` | `03/16 14:23:45` | 月/日 时间 |
## 自定义 Formatter
### 简单自定义
```cpp
#include "cflog/cflog_format.h"
class MyFormatter : public IFormatter {
public:
std::string format_me(const LogRecord& r) override {
return "[" + std::string(to_string(r.lvl)) + "] " + r.msg;
}
bool configurable() const override {
return false; // 不支持配置
}
};
```text
### 可配置自定义
```cpp
class ConfigurableFormatter : public IFormatter {
public:
ConfigurableFormatter() {
config_ = std::make_shared<FormatterConfig>();
}
std::string format_me(const LogRecord& r) override {
std::string result;
auto flags = config_->get_flags();
if ((flags & FormatterFlag::TIMESTAMP)) {
result += format_time(r.timestamp) + " ";
}
if ((flags & FormatterFlag::LEVEL)) {
result += "[" + std::string(to_string(r.lvl)) + "] ";
}
if ((flags & FormatterFlag::MESSAGE)) {
result += r.msg;
}
return result;
}
bool configurable() const override { return true; }
bool set_config(std::shared_ptr<FormatterConfig> config) override {
if (config) {
config_ = config;
return true;
}
return false;
}
std::shared_ptr<FormatterConfig> get_config() const override {
return config_;
}
private:
std::shared_ptr<FormatterConfig> config_;
std::string format_time(const cflog_timestamp_t& tp) {
// 实现时间格式化...
return "";
}
};
```text
## 常见格式示例
### JSON 格式
```cpp
class JsonFormatter : public IFormatter {
public:
std::string format_me(const LogRecord& r) override {
std::ostringstream oss;
oss << "{"
<< "\"timestamp\":\"" << format_timestamp(r) << "\","
<< "\"level\":\"" << to_string(r.lvl) << "\","
<< "\"tag\":\"" << r.tag << "\","
<< "\"message\":\"" << r.msg << "\","
<< "\"file\":\"" << r.loc.file_name() << "\","
<< "\"line\":" << r.loc.line()
<< "}";
return oss.str();
}
private:
std::string format_timestamp(const LogRecord& r) {
// 实现 ISO 8601 格式...
return "";
}
};
```text
### Syslog 格式
```cpp
class SyslogFormatter : public IFormatter {
public:
std::string format_me(const LogRecord& r) override {
std::ostringstream oss;
// 优先级代码 (facility * 8 + severity)
int priority = 1 * 8 + static_cast<int>(r.lvl);
oss << "<" << priority << ">";
// 时间戳
oss << format_timestamp(r) << " ";
// 主机名和程序
oss << "myapp" << " ";
// 消息
oss << r.tag << ": " << r.msg;
return oss.str();
}
private:
std::string format_timestamp(const LogRecord& r) {
// 实现 RFC 3164 格式...
return "";
}
};
```text
## 使用 FormatterFactory
### 注册和使用
```cpp
FormatterFactory factory;
// 注册
factory.register_formatter("custom", []() {
return std::make_shared<MyFormatter>();
});
// 创建
auto formatter = factory.create("custom");
// 获取或创建(带缓存)
auto cached = factory.get_or_create("custom");
```bash
## 选择建议
| 场景 | 推荐_formatter |
|------|---------------|
| 控制台输出(开发) | `AsciiColorFormatter` + `COLOR` |
| 控制台输出(生产) | `AsciiColorFormatter` 无 `COLOR` |
| 文件输出 | `FileFormatter` |
| 最小输出 | `AsciiColorFormatter` + `MINIMAL` |
| 详细调试 | `AsciiColorFormatter` + `VERBOSE` |
| 自定义格式 | 继承 `IFormatter` |
## 下一步
- 学习 [Sink 详解](./sinks.md)
- 阅读 [高级用法](./advanced_usage.md)
## 相关文档
- [Sink 详解](./sinks.md)
- [高级用法](./advanced_usage.md)
- [API 参考](../../../../desktop/base/logger/api_reference.md)