KDSPDSetup
Small library to initialize spdlog loggers from a toml configuration file.
Loading...
Searching...
No Matches
setup.cpp
Go to the documentation of this file.
1/*
2 This file is part of KDSpdSetup.
3
4 SPDX-FileCopyrightText: 2023 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
5
6 SPDX-License-Identifier: MIT
7
8 Contact KDAB at <info@kdab.com> for commercial licensing options.
9*/
10#include "setup.h"
11
12#include <iostream>
13
14using std::literals::string_literals::operator""s;
15
17
18void handleMultipleFileSink(toml::string &&typeStr, toml::table &&sinkTable, spdlog::sink_ptr &sinkPtr, bool const &truncate)
19{
20 auto baseFilename = sinkTable.at("base_filename").as_string();
21 auto maxFiles = (sinkTable.contains("max_files")) ? static_cast<uint16_t>(sinkTable.at("max_files").as_integer()) : uint16_t{ 0 };
22
24 sinkPtr = details::genFromRotateStr(std::move(typeStr), std::move(sinkTable), std::move(baseFilename), maxFiles);
25 }
26
27 else if (details::inTypelist(typeStr, details::dailyStrs)) {
28 sinkPtr = details::genFromDailyStr(std::move(typeStr), std::move(sinkTable), truncate, std::move(baseFilename), maxFiles);
29 }
30}
31
32void handleTruncatableSink(toml::string &&typeStr, toml::table &&sinkTable, spdlog::sink_ptr &sinkPtr)
33{
34 auto const truncate = (sinkTable.contains("truncate")) ? sinkTable.at("truncate").as_boolean() : false;
35
37 sinkPtr = details::genFromFileStr(std::move(typeStr), std::move(sinkTable), truncate);
39 handleMultipleFileSink(std::move(typeStr), std::move(sinkTable), sinkPtr, truncate);
40 }
41}
42
43void setupSink(toml::table &&sinkTable)
44{
45 spdlog::sink_ptr sinkPtr;
46
47 auto const name = sinkTable.at("name").as_string();
48 auto typeStr = sinkTable.at("type").as_string();
49
50 bool ok = false;
52 if (details::inTypelist(typeStr, typeList)) {
53 ok = true;
54 break;
55 }
56 }
57
58 if (!ok)
59 throw std::out_of_range("KDSPDSetup: sink type "s + typeStr.str + " is not valid"s);
60
61 toml::string level = "";
62 if (sinkTable.contains("level")) {
63 level = sinkTable.at("level").as_string();
64 }
65
68 handleTruncatableSink(std::move(typeStr), std::move(sinkTable), sinkPtr);
69 }
70
72 sinkPtr = details::genFromNullOrStdStr(std::move(typeStr));
73 }
74
75 else if (details::inTypelist(typeStr, details::linuxStrs)) {
76#ifdef __linux__
77 sinkPtr = details::genFromLinuxStr(std::move(typeStr), std::move(sinkTable));
78#else
79 return;
80#endif
81 } else if (details::inTypelist(typeStr, details::winStrs)) {
82#ifdef _WIN32
83 sinkPtr = details::genFromWinStr(std::move(typeStr));
84#else
85 return;
86#endif
87 }
88
89 if (level != "") {
90 if (!details::levelMap.contains(level))
91 throw std::out_of_range("KDSPDSetup: level "s + level.str + " not found"s);
92
93 sinkPtr->set_level(details::levelMap.at(level));
94 }
95
96 details::SPDMaps::emplaceSinkMap(std::make_pair(name, sinkPtr));
97}
98
99void setupSinks(toml::value const &data)
100{
101 auto sinks = toml::find<std::vector<toml::table>>(data, "sink");
102
103 for (auto &&sinkTable : sinks) {
104 setupSink(std::move(sinkTable));
105 }
106}
107
108void setupPatterns(toml::value const &data)
109{
110 if (data.contains("global_pattern")) {
111 auto const globalPattern = toml::find<toml::string>(data, "global_pattern");
112 spdlog::set_pattern(globalPattern);
113 }
114
115 if (data.contains("pattern")) {
116 auto const patterns = toml::find<std::vector<toml::table>>(data, "pattern");
117
118 for (auto &&patternTable : patterns) {
119 auto const name = patternTable.at("name").as_string();
120 auto const value = patternTable.at("value").as_string();
121
122 details::SPDMaps::emplacePatternMap(std::make_pair(name, value));
123 }
124 }
125}
126
127void setupThreadPools(toml::value const &data)
128{
129 if (data.contains("global_thread_pool")) {
130 auto const globalThreadPool = toml::find(data, "global_thread_pool");
131
132 auto const queueSize = toml::find<std::size_t>(globalThreadPool, "queue_size");
133 auto const numThreads = toml::find<std::size_t>(globalThreadPool, "num_threads");
134 spdlog::init_thread_pool(queueSize, numThreads);
135 }
136
137 if (data.contains("thread_pool")) {
138 auto const threadPools = toml::find<std::vector<toml::table>>(data, "thread_pool");
139
140 for (auto &&poolTable : threadPools) {
141 auto const name = poolTable.at("name").as_string();
142 auto const queueSize = static_cast<std::size_t>(poolTable.at("queue_size").as_integer());
143 auto const numThreads = static_cast<std::size_t>(poolTable.at("num_threads").as_integer());
144
145 details::SPDMaps::emplaceThreadPoolMap(std::make_pair(name, std::make_pair(queueSize, numThreads)));
146 }
147 }
148}
149
150void registerAsynchronousLogger(toml::table const &loggerTable, toml::string const &name, std::vector<spdlog::sink_ptr> const &sinkList,
151 toml::string const &pattern)
152{
153 auto const threadPool = (loggerTable.contains("thread_pool")) ? loggerTable.at("thread_pool").as_string() : "";
154
155 static std::shared_ptr<spdlog::details::thread_pool> threadPoolPtr;
156
157 if (threadPool != "") {
158 if (!details::SPDMaps::threadPoolMap().contains(threadPool))
159 throw std::out_of_range("KDSPDSetup: threadpool "s + threadPool.str + " not found"s);
160
161 auto const threadPoolPair = details::SPDMaps::threadPoolMap().at(threadPool);
162 auto const queueSize = threadPoolPair.first;
163 auto const numThreads = threadPoolPair.second;
164 threadPoolPtr = std::make_shared<spdlog::details::thread_pool>(queueSize, numThreads);
165 } else {
166 threadPoolPtr = spdlog::thread_pool();
167 }
168
169 auto const overflowPolicy =
170 (loggerTable.contains("overflow_policy")) ? loggerTable.at("overflow_policy").as_string() : "block";
171
172 if (!details::overflowMap.contains(overflowPolicy))
173 throw std::out_of_range("KDSPDSetup: overflow policy "s + overflowPolicy.str + " not found"s);
174
175 auto logger = std::make_shared<spdlog::async_logger>(name, sinkList.begin(), sinkList.end(), std::move(threadPoolPtr),
176 details::overflowMap.at(overflowPolicy));
177
178 if (pattern != "") {
179 logger->set_pattern(pattern);
180 }
181
182 spdlog::register_logger(logger);
183}
184
185void registerSynchronousLogger(toml::table const &loggerTable, toml::string const &name, std::vector<spdlog::sink_ptr> const &sinkList,
186 toml::string const &pattern)
187{
188 auto logger = std::make_shared<spdlog::logger>(name, sinkList.cbegin(), sinkList.cend());
189 if (pattern != "") {
190 logger->set_pattern(static_cast<std::string>(pattern));
191 }
192
193 if (loggerTable.contains("level")) {
194 auto const level = loggerTable.at("level").as_string();
195
196 if (!details::levelMap.contains(level))
197 throw std::out_of_range("KDSPDSetup: level "s + level.str + " not found"s);
198
199 logger->set_level(details::levelMap.at(level));
200 }
201
202 spdlog::register_logger(logger);
203}
204
205void setupLogger(toml::table const &loggerTable)
206{
207 auto const name = loggerTable.at("name").as_string();
208 if (spdlog::get(name) != nullptr) {
209 return;
210 }
211
212 auto const sinks = loggerTable.at("sinks").as_array();
213
214 auto sinkList = std::vector<spdlog::sink_ptr>{};
215 for (auto &&sink : sinks) {
216 if (details::SPDMaps::sinkMap().contains(sink.as_string())) {
217 sinkList.emplace_back(details::SPDMaps::sinkMap().at(sink.as_string()));
218 } else {
219 // ignore sink instead of throwing, but notify that this happens
220 std::cerr << "KDSPDSetup: setting up logger " << name
221 << " - skipped sink " << sink.as_string().str << " as it was not found";
222 }
223 }
224
225 std::string pattern = "";
226
227 if (loggerTable.contains("pattern")) {
228 if (!details::SPDMaps::patternMap().contains(loggerTable.at("pattern").as_string()))
229 throw std::out_of_range("KDSPDSetup: pattern "s + loggerTable.at("pattern").as_string().str + " not found"s);
230
231 pattern = details::SPDMaps::patternMap().at(loggerTable.at("pattern").as_string());
232 }
233
234 auto const type = (loggerTable.contains("type")) ? loggerTable.at("type").as_string() : "";
235
236 if (type == "async") {
237 registerAsynchronousLogger(loggerTable, name, sinkList, pattern);
238 } else {
239 registerSynchronousLogger(loggerTable, name, sinkList, pattern);
240 }
241}
242
243void setupLoggers(toml::value const &data)
244{
245 auto const loggers = toml::find<std::vector<toml::table>>(data, "logger");
246 for (auto &&loggerTable : loggers) {
247 setupLogger(loggerTable);
248 }
249}
250
251} // namespace KDSPDSetup::setup
static void emplaceSinkMap(std::pair< toml::string, spdlog::sink_ptr > &&_pr)
Emplace a pair in the private member KDSPDSetup::details::SPDMaps::mSinkMap. This function is called ...
Definition details.cpp:26
static auto sinkMap() -> std::map< toml::string, spdlog::sink_ptr > const &
Getter method for the private member KDSPDSetup::details::SPDMaps::mSinkMap. Used to index the map an...
Definition details.cpp:14
static auto patternMap() -> std::map< toml::string, toml::string > const &
Getter method for the private member KDSPDSetup::details::SPDMaps::mPatternMap. Used to index the map...
Definition details.cpp:18
static void emplaceThreadPoolMap(std::pair< toml::string, std::pair< std::size_t, std::size_t > > &&_pr)
Emplace a pair in the private member KDSPDSetup::details::SPDMaps::mThreadPoolMap....
Definition details.cpp:34
static void emplacePatternMap(std::pair< toml::string, toml::string > &&_pr)
Emplace a pair in the private member KDSPDSetup::details::SPDMaps::mSinkMap. This function is called ...
Definition details.cpp:30
static auto threadPoolMap() -> std::map< toml::string, std::pair< std::size_t, std::size_t > > const &
Getter method for the private member KDSPDSetup::details::SPDMaps::mThreadPoolMap....
Definition details.cpp:22
static auto const linuxStrs
Vector of strings of spdlog syslog sink typenames. Used when matching a type string from a TOML table...
Definition details.h:87
static auto const dailyStrs
Vector of strings of spdlog daily file sink typenames. Used when matching a type string from a TOML t...
Definition details.h:73
static auto const nullStrs
Vector of strings of spdlog null sink typenames. Used when matching a type string from a TOML table t...
Definition details.h:80
auto genFromDailyStr(toml::string &&typeStr, toml::table &&sinkTable, bool const &truncate, toml::string &&baseFilename, uint16_t const &maxFiles) -> spdlog::sink_ptr
Return the result of calling KDSPDSetup::details::createDailyFileSinkPtr with the correct template ar...
Definition details.cpp:147
static auto const fileStrs
Vector of strings of spdlog basic file sink typenames. Used when matching a type string from a TOML t...
Definition details.h:59
bool inTypelist(std::string const &typeStr, std::vector< std::string > const &strList)
Returns true if a string typeStr is present in a vector strList, and false if not....
Definition details.cpp:39
static auto const rotateStrs
Vector of strings of spdlog rotating file sink typenames. Used when matching a type string from a TOM...
Definition details.h:66
static auto const winStrs
Vector of strings of spdlog MSVC sink typenames. Used when matching a type string from a TOML table t...
Definition details.h:94
static auto const overflowMap
A simple map associating strings of spdlog::async_overflow_policy names to the enums themselves....
Definition details.h:118
auto genFromFileStr(toml::string &&typeStr, toml::table &&sinkTable, bool const &truncate) -> spdlog::sink_ptr
Return the result of calling KDSPDSetup::details::createFileSinkPtr with the correct template argumen...
Definition details.cpp:122
auto genFromRotateStr(toml::string &&typeStr, toml::table &&sinkTable, toml::string &&baseFilename, std::size_t const &maxFiles) -> spdlog::sink_ptr
Return the result of calling KDSPDSetup::details::createRotatingFileSinkPtr with the correct template...
Definition details.cpp:134
static auto const levelMap
A simple map associating strings of spdlog::level::level_enum names to the enums themselves....
Definition details.h:101
auto genFromNullOrStdStr(toml::string &&typeStr) -> spdlog::sink_ptr
Return the result of calling KDSPDSetup::details::createStdoutSinkPtr with the correct template argum...
Definition details.cpp:160
static auto const stdStrs
Vector of strings of spdlog standard output sink typenames. Used when matching a type string from a T...
Definition details.h:48
This namespace contains the functions directly called by KDSPDSetup::setupFrom, along with helpers ca...
Definition setup.cpp:16
void setupLoggers(toml::value const &data)
Using data read from a toml file, extract vector of tables representing every logger specified....
Definition setup.cpp:243
void setupPatterns(toml::value const &data)
Using data read from a toml file, search for the key global_pattern. If it exists,...
Definition setup.cpp:108
void setupLogger(toml::table const &loggerTable)
Given a table representation of a logger whose name is not already registered with spdlog,...
Definition setup.cpp:205
void setupSink(toml::table &&sinkTable)
Given a table representation of a sink, creates an spdlog::sink_ptr, and evaluates the type of sink s...
Definition setup.cpp:43
void registerSynchronousLogger(toml::table const &loggerTable, toml::string const &name, std::vector< spdlog::sink_ptr > const &sinkList, toml::string const &pattern)
Creates an std::shared_ptr<spdlog::logger> initialized with name and the sink pointers in sinklist,...
Definition setup.cpp:185
void handleMultipleFileSink(toml::string &&typeStr, toml::table &&sinkTable, spdlog::sink_ptr &sinkPtr, bool const &truncate)
Helper function for setting up sinks that use multiple files. The function extracts values for base_f...
Definition setup.cpp:18
void setupSinks(toml::value const &data)
Using data read from a toml file, extract vector of tables representing every sink specified....
Definition setup.cpp:99
void setupThreadPools(toml::value const &data)
Using data read from a toml file, search for a table global_thread_pool, and initialize it with the s...
Definition setup.cpp:127
void handleTruncatableSink(toml::string &&typeStr, toml::table &&sinkTable, spdlog::sink_ptr &sinkPtr)
Helper function for setting up file-based sinks that require a truncate argument in their constructor...
Definition setup.cpp:32
void registerAsynchronousLogger(toml::table const &loggerTable, toml::string const &name, std::vector< spdlog::sink_ptr > const &sinkList, toml::string const &pattern)
Creates an std::shared_ptr<spdlog::async_logger> initialized with name, the sink pointers in sinklist...
Definition setup.cpp:150