Skip to content

Commit d0bceb5

Browse files
committed
feat: Use spdlog logger
1 parent 2600198 commit d0bceb5

25 files changed

+642
-547
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ include(deps/Threads)
5858
include(deps/libfmt)
5959
include(deps/cassandra)
6060
include(deps/libbacktrace)
61+
include(deps/spdlog)
6162

6263
add_subdirectory(src)
6364
add_subdirectory(tests)

benchmarks/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@ target_sources(
1414
include(deps/gbench)
1515

1616
target_include_directories(clio_benchmark PRIVATE .)
17-
target_link_libraries(clio_benchmark PUBLIC clio_util benchmark::benchmark_main)
17+
target_link_libraries(clio_benchmark PUBLIC clio_util benchmark::benchmark_main spdlog::spdlog)
1818
set_target_properties(clio_benchmark PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})

benchmarks/util/log/LoggerBenchmark.cpp

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,26 +22,35 @@
2222
#include "util/prometheus/Prometheus.hpp"
2323

2424
#include <benchmark/benchmark.h>
25-
#include <boost/log/core/core.hpp>
26-
#include <boost/log/utility/setup/common_attributes.hpp>
25+
#include <spdlog/async.h>
26+
#include <spdlog/async_logger.h>
27+
#include <spdlog/spdlog.h>
2728

2829
#include <barrier>
2930
#include <chrono>
3031
#include <cstddef>
3132
#include <filesystem>
33+
#include <memory>
3234
#include <string>
3335
#include <thread>
36+
#include <utility>
3437
#include <vector>
3538

3639
using namespace util;
3740

41+
static constexpr auto kLOG_FORMAT = "%Y-%m-%d %H:%M:%S.%f %^(%@) [%t] %n:%L%$ %v";
42+
3843
struct BenchmarkLoggingInitializer {
39-
static constexpr auto kLOG_FORMAT = "%TimeStamp% (%SourceLocation%) [%ThreadID%] %Channel%:%Severity% %Message%";
44+
static std::shared_ptr<spdlog::sinks::sink>
45+
createFileSink(LogService::FileLoggingParams const& params)
46+
{
47+
return LogService::createFileSink(params);
48+
}
4049

41-
static void
42-
initFileLogging(LogService::FileLoggingParams const& params)
50+
static Logger
51+
getLogger(std::shared_ptr<spdlog::logger> logger)
4352
{
44-
LogService::initFileLogging(params, kLOG_FORMAT);
53+
return Logger(std::move(logger));
4554
}
4655
};
4756

@@ -62,7 +71,7 @@ uniqueLogDir()
6271
static void
6372
benchmarkConcurrentFileLogging(benchmark::State& state)
6473
{
65-
boost::log::add_common_attributes();
74+
spdlog::drop_all();
6675

6776
auto const numThreads = static_cast<size_t>(state.range(0));
6877
auto const messagesPerThread = static_cast<size_t>(state.range(1));
@@ -74,12 +83,12 @@ benchmarkConcurrentFileLogging(benchmark::State& state)
7483
state.PauseTiming();
7584

7685
std::filesystem::create_directories(logDir);
86+
spdlog::init_thread_pool(8192, 1);
7787

78-
BenchmarkLoggingInitializer::initFileLogging({
88+
auto fileSink = BenchmarkLoggingInitializer::createFileSink({
7989
.logDir = logDir,
8090
.rotationSizeMB = 5,
81-
.dirMaxSizeMB = 125,
82-
.rotationHours = 24,
91+
.dirMaxFiles = 25,
8392
});
8493

8594
std::vector<std::thread> threads;
@@ -92,10 +101,16 @@ benchmarkConcurrentFileLogging(benchmark::State& state)
92101
});
93102

94103
for (size_t threadNum = 0; threadNum < numThreads; ++threadNum) {
95-
threads.emplace_back([threadNum, messagesPerThread, &barrier]() {
96-
barrier.arrive_and_wait();
104+
threads.emplace_back([threadNum, messagesPerThread, fileSink, &barrier]() {
105+
std::string const channel = "Thread_" + std::to_string(threadNum);
106+
auto logger = std::make_shared<spdlog::async_logger>(
107+
channel, fileSink, spdlog::thread_pool(), spdlog::async_overflow_policy::block
108+
);
109+
logger->set_pattern(kLOG_FORMAT);
110+
spdlog::register_logger(logger);
111+
Logger const threadLogger = BenchmarkLoggingInitializer::getLogger(std::move(logger));
97112

98-
Logger const threadLogger("Thread_" + std::to_string(threadNum));
113+
barrier.arrive_and_wait();
99114

100115
for (size_t messageNum = 0; messageNum < messagesPerThread; ++messageNum) {
101116
LOG(threadLogger.info()) << "Test log message #" << messageNum;
@@ -106,10 +121,9 @@ benchmarkConcurrentFileLogging(benchmark::State& state)
106121
for (auto& thread : threads) {
107122
thread.join();
108123
}
109-
boost::log::core::get()->flush();
124+
spdlog::shutdown();
110125

111126
auto const end = std::chrono::high_resolution_clock::now();
112-
113127
state.SetIterationTime(std::chrono::duration_cast<std::chrono::duration<double>>(end - start).count());
114128

115129
std::filesystem::remove_all(logDir);
@@ -129,7 +143,7 @@ BENCHMARK(benchmarkConcurrentFileLogging)
129143
// Number of threads
130144
{1, 2, 4, 8},
131145
// Messages per thread
132-
{10'000, 100'000, 500'000},
146+
{10'000, 100'000, 500'000, 1'000'000, 10'000'000},
133147
})
134148
->UseManualTime()
135149
->Unit(benchmark::kMillisecond);

cmake/deps/spdlog.cmake

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
find_package(spdlog REQUIRED)
2+
3+
if (NOT TARGET spdlog::spdlog)
4+
message(FATAL_ERROR "spdlog::spdlog target not found")
5+
endif ()

conan.lock

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"xxhash/0.8.2#7856c968c985b2981b707ee8f2413b2b%1754325010.01",
66
"xrpl/2.5.0@clio/boost-odr#f68e48da1490c0a583052e4f068ada55%1754325014.392",
77
"sqlite3/3.47.0#7a0904fd061f5f8a2366c294f9387830%1754325009.708",
8+
"spdlog/1.15.3#3ca0e9e6b83af4d0151e26541d140c86%1748617970.519",
89
"soci/4.0.3#a9f8d773cd33e356b5879a4b0564f287%1754412158.144",
910
"re2/20230301#dfd6e2bf050eb90ddd8729cfb4c844a4%1754412148.014",
1011
"rapidjson/cci.20220822#1b9d8c2256876a154172dc5cfbe447c6%1754325007.656",
@@ -54,4 +55,4 @@
5455
]
5556
},
5657
"config_requires": []
57-
}
58+
}

conanfile.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ class ClioConan(ConanFile):
3333
'openssl/1.1.1v',
3434
'xrpl/2.5.0@clio/boost-odr',
3535
'zlib/1.3.1',
36-
'libbacktrace/cci.20210118'
36+
'libbacktrace/cci.20210118',
37+
'spdlog/1.15.3',
3738
]
3839

3940
default_options = {

docs/config-description.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -439,13 +439,21 @@ This document provides a list of all available Clio configuration properties in
439439
- **Constraints**: The value must be one of the following: `trace`, `debug`, `info`, `warning`, `error`, `fatal`, `count`.
440440
- **Description**: The general logging level of Clio. This level is applied to all log channels that do not have an explicitly defined logging level.
441441

442-
### log_format
442+
### spdlog_format
443443

444444
- **Required**: True
445445
- **Type**: string
446-
- **Default value**: `%TimeStamp% (%SourceLocation%) [%ThreadID%] %Channel%:%Severity% %Message%`
446+
- **Default value**: `%Y-%m-%d %H:%M:%S.%f %^(%@) [%t] %n:%L%$ %v`
447447
- **Constraints**: None
448-
- **Description**: The format string for log messages. The format is described here: <https://www.boost.org/doc/libs/1_83_0/libs/log/doc/html/log/tutorial/formatters.html>.
448+
- **Description**: The format string for log messages using spdlog format patterns. Documentation can be found at: <https://github.com/gabime/spdlog/wiki/Custom-formatting>.
449+
450+
### spdlog_async
451+
452+
- **Required**: True
453+
- **Type**: boolean
454+
- **Default value**: `True`
455+
- **Constraints**: None
456+
- **Description**: Whether spdlog is asynchronous or not.
449457

450458
### log_to_console
451459

@@ -471,21 +479,13 @@ This document provides a list of all available Clio configuration properties in
471479
- **Constraints**: The minimum value is `1`. The maximum value is `4294967295`.
472480
- **Description**: The log rotation size in megabytes. When the log file reaches this particular size, a new log file starts.
473481

474-
### log_directory_max_size
475-
476-
- **Required**: True
477-
- **Type**: int
478-
- **Default value**: `51200`
479-
- **Constraints**: The minimum value is `1`. The maximum value is `4294967295`.
480-
- **Description**: The maximum size of the log directory in megabytes.
481-
482-
### log_rotation_hour_interval
482+
### log_directory_max_files
483483

484484
- **Required**: True
485485
- **Type**: int
486-
- **Default value**: `12`
486+
- **Default value**: `25`
487487
- **Constraints**: The minimum value is `1`. The maximum value is `4294967295`.
488-
- **Description**: Represents the interval (in hours) for log rotation. If the current log file reaches this value in logging, a new log file starts.
488+
- **Description**: The maximum number of log files in the directory.
489489

490490
### log_tag_style
491491

docs/examples/config/example-config.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,14 +122,15 @@
122122
"compress_reply": true
123123
},
124124
"log_level": "info",
125-
// Log format (this is the default format)
126-
"log_format": "%TimeStamp% (%SourceLocation%) [%ThreadID%] %Channel%:%Severity% %Message%",
125+
// Log format using spdlog format patterns (this is the default format)
126+
"spdlog_format": "%Y-%m-%d %H:%M:%S.%f %^(%@) [%t] %n:%L%$ %v",
127+
// Whether spdlog is asynchronous or not.
128+
"spdlog_async": true,
127129
"log_to_console": true,
128130
// Clio logs to file in the specified directory only if "log_directory" is set
129131
// "log_directory": "./clio_log",
130132
"log_rotation_size": 2048,
131-
"log_directory_max_size": 51200,
132-
"log_rotation_hour_interval": 12,
133+
"log_directory_max_files": 25,
133134
"log_tag_style": "uint",
134135
"extractor_threads": 8,
135136
"read_only": false,

docs/logging.md

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,26 @@ Clio provides several logging options, which all are configurable via the config
66

77
The minimum level of severity at which the log message will be outputted by default. Severity options are `trace`, `debug`, `info`, `warning`, `error`, `fatal`. Defaults to `info`.
88

9-
## `log_format`
9+
## `spdlog_format`
1010

11-
The format of log lines produced by Clio. Defaults to `"%TimeStamp% (%SourceLocation%) [%ThreadID%] %Channel%:%Severity% %Message%"`.
11+
The format of log lines produced by Clio using spdlog format patterns. Defaults to `"%Y-%m-%d %H:%M:%S.%f %^(%@) [%t] %n:%L%$ %v"`.
1212

1313
Each of the variables expands like so:
1414

15-
- `TimeStamp`: The full date and time of the log entry
16-
- `SourceLocation`: A partial path to the c++ file and the line number in said file (`source/file/path:linenumber`)
17-
- `ThreadID`: The ID of the thread the log entry is written from
18-
- `Channel`: The channel that this log entry was sent to
19-
- `Severity`: The severity (aka log level) the entry was sent at
20-
- `Message`: The actual log message
15+
- `%^`: Start color range
16+
- `%Y-%m-%d %H:%M:%S.%f`: The full date and time of the log entry with microsecond precision
17+
- `%@`: A partial path to the c++ file and the line number in said file (`source/file/path:linenumber`)
18+
- `%t`: The ID of the thread the log entry is written from
19+
- `%n`: The logger name (channel) that this log entry was sent to
20+
- `%l`: The severity (aka log level) the entry was sent at
21+
- `%$`: End color range
22+
- `%v`: The actual log message
23+
24+
For more information about spdlog format patterns, see: <https://github.com/gabime/spdlog/wiki/Custom-formatting>
25+
26+
## `spdlog_async`
27+
28+
Whether spdlog is asynchronous or not.
2129

2230
## `log_channels`
2331

@@ -56,16 +64,9 @@ If the option is not specified, the logs are not written to a file.
5664

5765
The max size of the log file in **megabytes** before it will rotate into a smaller file. Defaults to 2GB.
5866

59-
## `log_directory_max_size`
60-
61-
The max size of the log directory in **megabytes** before old log files will be deleted to free up space. Defaults to 50GB.
67+
## `log_directory_max_files`
6268

63-
## `log_rotation_hour_interval`
64-
65-
The time interval in **hours** after the last log rotation to automatically rotate the current log file. Defaults to 12 hours.
66-
67-
> [!NOTE]
68-
> Log rotation based on time occurs in conjunction with size-based log rotation. For example, if a size-based log rotation occurs, the timer for the time-based rotation will reset.
69+
The max number of log files in the directory before old log files will be deleted to free up space. Defaults to 25.
6970

7071
## `log_tag_style`
7172

src/app/Stopper.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ class Stopper {
108108

109109
ioc.stop();
110110
LOG(util::LogService::info()) << "io_context stopped";
111+
112+
util::LogService::shutdown();
111113
};
112114
}
113115
};

0 commit comments

Comments
 (0)