3131#include < spdlog/async.h>
3232#include < spdlog/async_logger.h>
3333#include < spdlog/common.h>
34+ #include < spdlog/details/log_msg.h>
35+ #include < spdlog/formatter.h>
3436#include < spdlog/logger.h>
37+ #include < spdlog/pattern_formatter.h>
3538#include < spdlog/sinks/rotating_file_sink.h>
3639#include < spdlog/sinks/stdout_color_sinks.h>
3740#include < spdlog/spdlog.h>
4144#include < cstddef>
4245#include < cstdint>
4346#include < filesystem>
47+ #include < iostream>
4448#include < memory>
4549#include < optional>
4650#include < string>
@@ -120,26 +124,63 @@ getSeverityLevel(std::string_view logLevel)
120124 std::unreachable ();
121125}
122126
127+ /* *
128+ * @brief Custom formatter that filters out critical messages
129+ *
130+ * This formatter only processes and formats messages with severity level less than critical.
131+ * Critical messages will be handled separately.
132+ */
133+ class NonCriticalFormatter : public spdlog ::formatter {
134+ public:
135+ NonCriticalFormatter (std::unique_ptr<spdlog::formatter> wrappedFormatter)
136+ : wrapped_formatter_(std::move(wrappedFormatter))
137+ {
138+ }
139+
140+ void
141+ format (spdlog::details::log_msg const & msg, spdlog::memory_buf_t & dest) override
142+ {
143+ // Only format messages with severity less than critical
144+ if (msg.level != spdlog::level::critical) {
145+ wrapped_formatter_->format (msg, dest);
146+ }
147+ }
148+
149+ std::unique_ptr<formatter>
150+ clone () const override
151+ {
152+ return std::make_unique<NonCriticalFormatter>(wrapped_formatter_->clone ());
153+ }
154+
155+ private:
156+ std::unique_ptr<spdlog::formatter> wrapped_formatter_;
157+ };
158+
123159/* *
124160 * @brief Initializes console logging.
125161 *
126162 * @param logToConsole A boolean indicating whether to log to console.
163+ * @param format A string representing the log format.
127164 * @return Vector of sinks for console logging.
128165 */
129166static std::vector<spdlog::sink_ptr>
130- createConsoleSinks (bool logToConsole)
167+ createConsoleSinks (bool logToConsole, std::string const & format )
131168{
132169 std::vector<spdlog::sink_ptr> sinks;
133170
134171 if (logToConsole) {
135172 auto consoleSink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
136173 consoleSink->set_level (spdlog::level::trace);
174+ consoleSink->set_formatter (
175+ std::make_unique<NonCriticalFormatter>(std::make_unique<spdlog::pattern_formatter>(format))
176+ );
137177 sinks.push_back (std::move (consoleSink));
138178 }
139179
140180 // Always add stderr sink for fatal logs
141181 auto stderrSink = std::make_shared<spdlog::sinks::stderr_color_sink_mt>();
142182 stderrSink->set_level (spdlog::level::critical);
183+ stderrSink->set_formatter (std::make_unique<spdlog::pattern_formatter>(format));
143184 sinks.push_back (std::move (stderrSink));
144185
145186 return sinks;
@@ -153,7 +194,7 @@ createConsoleSinks(bool logToConsole)
153194 * @return File sink for logging.
154195 */
155196spdlog::sink_ptr
156- LogService::createFileSink (FileLoggingParams const & params)
197+ LogService::createFileSink (FileLoggingParams const & params, std::string const & format )
157198{
158199 std::filesystem::path const dirPath (params.logDir );
159200 // the below are taken from user in MB, but spdlog needs it to be in bytes
@@ -163,6 +204,7 @@ LogService::createFileSink(FileLoggingParams const& params)
163204 (dirPath / " clio.log" ).string (), rotationSize, params.dirMaxFiles
164205 );
165206 fileSink->set_level (spdlog::level::trace);
207+ fileSink->set_formatter (std::make_unique<spdlog::pattern_formatter>(format));
166208
167209 return fileSink;
168210}
@@ -229,11 +271,13 @@ LogService::init(config::ClioConfigDefinition const& config)
229271 data.isAsync = config.get <bool >(" log.is_async" );
230272 data.defaultSeverity = getSeverityLevel (config.get <std::string>(" log.level" ));
231273
274+ std::string const format = config.get <std::string>(" log.format" );
275+
232276 if (data.isAsync ) {
233277 spdlog::init_thread_pool (8192 , 1 );
234278 }
235279
236- data.allSinks = createConsoleSinks (config.get <bool >(" log.enable_console" ));
280+ data.allSinks = createConsoleSinks (config.get <bool >(" log.enable_console" ), format );
237281
238282 if (auto const logDir = config.maybeValue <std::string>(" log.directory" ); logDir.has_value ()) {
239283 std::filesystem::path const dirPath{logDir.value ()};
@@ -250,7 +294,7 @@ LogService::init(config::ClioConfigDefinition const& config)
250294 .rotationSizeMB = config.get <uint32_t >(" log.rotation_size" ),
251295 .dirMaxFiles = config.get <uint32_t >(" log.directory_max_files" ),
252296 };
253- data.allSinks .push_back (createFileSink (params));
297+ data.allSinks .push_back (createFileSink (params, format ));
254298 }
255299
256300 // get min severity per channel, can be overridden using the `log.channels` array
@@ -269,9 +313,6 @@ LogService::init(config::ClioConfigDefinition const& config)
269313
270314 spdlog::set_default_logger (spdlog::get (" General" ));
271315
272- std::string const format = config.get <std::string>(" log.format" );
273- spdlog::set_pattern (format);
274-
275316 LOG (LogService::info ()) << " Default log level = " << toString (data.defaultSeverity );
276317 return {};
277318}
0 commit comments