# easylog
**Repository Path**: yyx_dev/easylog
## Basic Information
- **Project Name**: easylog
- **Description**: 插件式的同步异步日志系统
- **Primary Language**: C++
- **License**: MulanPSL-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 3
- **Forks**: 1
- **Created**: 2023-07-20
- **Last Updated**: 2025-04-07
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# esylog
`esylog`是一个快速的、仅头文件的、跨平台支持的C++日志库。
## 项目特点
- 模仿spdlog实现
- 日志输出支持{fmt}库或C风格的格式串
- 版本仅需C++11
- 支持同步和异步两种日志器
- 异步日志器支持三种刷新方式,即时刷新、按秒刷新、总是刷新
- 支持多种落地位置,如标准输出和普通文件和滚动文件,并支持扩展
- 日志器注册表管理全局日志器
- 支持自定义日志消息格式
- 支持终端彩色打印
- 支持多线程写入
- 支持全局日志配置接口
- FATAL日志支持打印堆栈信息
## 使用示例
#### 默认日志器
最基本的全局的默认日志器,便于简单输出日志。
```cpp
esylog::debug("{}:{}", "I get a debug log", 1);
esylog::info ("{}:{}", "I get a info log", 2);
esylog::warn ("{}:{}", "I get a warn log", 3);
esylog::error("{}:{}", "I get a error log", 4);
esylog::fatal("{}:{}", "I get a fatal log", 5);
ESYLOG_DEBUG("{}:{}", "I get a debug log", 1)
ESYLOG_INFO( "{}:{}", "I get a info log", 2)
ESYLOG_WARN( "{}:{}", "I get a warn log", 3)
ESYLOG_ERROR("{}:{}", "I get a error log", 4)
ESYLOG_FATAL("{}:{}", "I get a fatal log", 5)
ESYLOG_LOGGER_DEBUG(lgr, "{}:{}", "I get a debug log", 1)
ESYLOG_LOGGER_INFO( lgr, "{}:{}", "I get a info log", 2)
ESYLOG_LOGGER_WARN( lgr, "{}:{}", "I get a warn log", 3)
ESYLOG_LOGGER_ERROR(lgr, "{}:{}", "I get a error log", 4)
ESYLOG_LOGGER_FATAL(lgr, "{}:{}", "I get a fatal log", 5)
```
#### 同步日志器
可自定义相关配置的同步日志器,日志输出由业务线程负责。
```cpp
logger_builder::ptr llb = std::make_shared();
llb->build_logger_type(logger_builder::sync);
llb->build_logger_name("sync");
llb->build_limit_level(level::debug);
llb->build_sinker();
logger::ptr lgr = llb->build();
lgr->info("{}:{}", "I get a info log", 1);
```
#### 异步日志器
可自定义日志器配置,日志输出交给异步工作线程处理,不会阻塞业务线程。
```cpp
logger_builder::ptr llb = std::make_shared();
llb->build_logger_type(logger_builder::async);
llb->build_logger_name("async");
llb->build_limit_level(level::debug);
llb->build_sinker();
llb->build_work_type(logger_builder::work_type::safe);
llb->build_thread_num();
llb->build_buffer_size();
llb->build_buffer_increment();
llb->build_buffer_threshold();
logger::ptr lgr = llb->build();
lgr->info("{}:{}", "I get a info log", 2);
```
异步日志器支持即时刷新,或者设置刷新时间,或者总是刷新
```cpp
lgr->flush();
lgr->set_flush_every(util::time::time_enum::t2sec);
lgr->set_always_flush();
```
#### 为日志器添加落地器
目前提供的落地器,有标准输出、普通文件、按时间滚动和按体积滚动共四种落地器。
```cpp
logger_builder::ptr llb = std::make_shared();
//...
llb->build_sinker();
llb->build_sinker();
llb->build_sinker(time_enum::t2sec);
llb->build_sinker(size_enum::m5MB);
logger::ptr lgr = llb->build();
lgr->info("I get a info log");
```
#### 日志器全局注册表
全局的日志器注册表,用来管理所有全局的日志器,可以添加和获取日志器。以便在项目的任意位置获取自定义的日志器。
```cpp
registry::instance()->add(lgr);
registry::instance()->get(name);
registry::instance()->default_logger();
```
#### 自定义日志格式
支持设置日志字符串的格式化规则,提供格式化规则串,日志格式化器会按照规则格式化日志。
```cpp
// 时间 %d
// 制表符 %T
// 线程编号 %t
// 日志等级 %p
// 日志器名 %c
// 源文件名 %f
// 行号 %l
// 函数名 %a
// 消息主体 %m
// 换行符 %n
// 百分号 %%
sinker::ptr sk = sinker_factory::create();
formatter fmtr("[%d{%F %H:%M:%S}][%p][%t][%c][%f:%l]%T%m [%a]%n");
sk->set_formatter(fmtr);
```
#### 全局配置接口
目前日志库提供一些全局的配置接口,以便进行全局配置。
```cpp
void set_level(level_enum lv);
void set_pattern(const std::string& p);
void set_colorful(bool color);
void set_color(const color_mode& cols);
void set_fn_pattern(const std::string& patt);
void set_max_file_size(size_enum size);
void set_max_live_time(time_enum time);
void set_max_history(size_t num);
void set_total_size_cap(size_enum size);
void set_work_type(worker_type type);
void set_thread_num(size_t num);
void set_buffer_size(size_t size);
void set_buffer_increment(size_t incr);
void set_buffer_threshold(size_t thre);
void add(const logger::ptr& logger);
bool has(const std::string& name);
logger::ptr get(const std::string& name);
logger::ptr default_logger();
```
## 性能测试
分别使用同步异步日志来输出一百万条日志,并计算每秒的日志输出条数以及输出量。
云服务器 Ubuntu22.04系统 2核2G 硬盘 40G 带宽3M
```txt
---------------- 同步日志性能测试 ----------------
测试开始,日志共 1000000 条,单条大小 100 Bytes,总大小 97656 KB
线程0: 输出日志 333333 条,耗时 4.776920 s
线程1: 输出日志 333333 条,耗时 4.803588 s
线程2: 输出日志 333333 条,耗时 4.837192 s
总耗时:4.776920 s
每秒输出日志条数 209339 条
每秒输出日志大小 20443 KB
---------------- 异步日志性能测试 ----------------
测试开始,日志共 1000000 条,单条大小 100 Bytes,总大小 97656 KB
线程1: 输出日志 333333 条,耗时 0.783362 s
线程2: 输出日志 333333 条,耗时 0.806406 s
线程0: 输出日志 333333 条,耗时 0.824926 s
总耗时:0.783362 s
每秒输出日志条数 1276549 条
每秒输出日志大小 124663 KB
```
RedmiBook14pro 2020 AMD R5 5500U 6核16G 硬盘 512G
```txt
---------------- 同步日志性能测试 ----------------
测试开始,日志共 1000000 条,单条大小 100 Bytes,总大小 97656 KB
线程0: 输出日志 333333 条,耗时 5.157611 s
线程1: 输出日志 333333 条,耗时 6.139245 s
线程2: 输出日志 333333 条,耗时 6.346160 s
总耗时:6.346160 s
每秒输出日志条数 1193888 条
每秒输出日志大小 118934 KB
---------------- 异步日志性能测试 ----------------
测试开始,日志共 1000000 条,单条大小 100 Bytes,总大小 97656 KB
线程1: 输出日志 333333 条,耗时 0.758197 s
线程2: 输出日志 333333 条,耗时 0.763640 s
线程0: 输出日志 333333 条,耗时 0.764615 s
总耗时:0.764615 s
每秒输出日志条数 1318918 条
每秒输出日志大小 128800 KB
```
iMac 2020 M1 macOS12.6 8核8G 硬盘 256G
```txt
---------------- 同步日志性能测试 ----------------
测试开始,日志共 1000000 条,单条大小 100 Bytes,总大小 97656 KB
线程0: 输出日志 333333 条,耗时 3.660836 s
线程1: 输出日志 333333 条,耗时 3.956032 s
线程2: 输出日志 333333 条,耗时 3.976212 s
总耗时:3.660836 s
每秒输出日志条数 273161 条
每秒输出日志大小 26675 KB
---------------- 异步日志性能测试 ----------------
测试开始,日志共 1000000 条,单条大小 100 Bytes,总大小 97656 KB
线程0: 输出日志 333333 条,耗时 0.661250 s
线程2: 输出日志 333333 条,耗时 0.704420 s
线程1: 输出日志 333333 条,耗时 0.706501 s
总耗时:0.661250 s
每秒输出日志条数 1512286 条
每秒输出日志大小 147684 KB
```
2核2G的服务器可轻松达到每秒输出一百万条日志的要求。
> 注:
> 如果您因缺少头文件而无法成功编译,那是因为我将这些文件安装到系统目录中了,
> 具体可以从该仓库下载 [third-party-libraries](https://gitee.com/yyx_dev/third-party-libraries) (该仓库存放一些常用的C/C++库)