9 #include "quill/core/Attributes.h" 10 #include "quill/core/Common.h" 11 #include "quill/core/LogLevel.h" 12 #include "quill/core/LoggerBase.h" 13 #include "quill/core/PatternFormatterOptions.h" 14 #include "quill/core/QuillError.h" 15 #include "quill/core/Spinlock.h" 20 #include <initializer_list> 24 #include <string_view> 53 QUILL_NODISCARD
LoggerBase* get_logger(std::string
const& logger_name)
const 56 LoggerBase* logger = _find_logger(logger_name);
61 QUILL_NODISCARD std::vector<LoggerBase*> get_all_loggers()
const 65 std::vector<LoggerBase*> loggers;
67 for (
auto const& elem : _loggers)
70 if (elem->is_valid_logger())
72 loggers.push_back(elem.get());
80 QUILL_NODISCARD
LoggerBase* get_valid_logger(std::string_view exclude_logger_substr = {})
const 85 for (
auto const& elem : _loggers)
88 if (elem->is_valid_logger())
91 if (exclude_logger_substr.empty() ||
92 elem->get_logger_name().find(exclude_logger_substr) == std::string::npos)
104 QUILL_NODISCARD
LoggerBase* get_valid_logger(std::vector<std::string>
const& exclude_logger_substrs)
const 107 for (
auto const& elem : _loggers)
109 if (elem->is_valid_logger())
111 bool excluded =
false;
112 for (
auto const& exclude_substr : exclude_logger_substrs)
114 if (!exclude_substr.empty() && elem->get_logger_name().find(exclude_substr) != std::string::npos)
131 QUILL_NODISCARD
size_t get_number_of_loggers()
const noexcept
134 return _loggers.size();
140 template <
typename TCallback>
145 for (
auto const& elem : _loggers)
161 template <
typename TLogger>
168 LoggerBase* logger_ptr = _find_logger(logger_name);
172 QUILL_THROW(
QuillError{
"Logger with name \"" + logger_name +
173 "\" is pending removal and cannot be recreated until the backend " 174 "completes logger cleanup. Use remove_logger_blocking() if you need " 175 "to recreate the logger synchronously."});
181 QuillError{
"Logger with name \"" + logger_name +
182 "\" already exists. " 183 "Use create_or_get_logger() if you want to retrieve the existing logger, " 184 "or choose a different name."});
187 std::unique_ptr<LoggerBase> new_logger{
188 new TLogger{logger_name,
static_cast<std::vector<std::shared_ptr<Sink>
>&&>(sinks),
189 pattern_formatter_options, clock_source, user_clock}};
191 _insert_logger(
static_cast<std::unique_ptr<LoggerBase>&&
>(new_logger));
193 logger_ptr = _find_logger(logger_name);
195 if (logger_ptr && _env_log_level)
200 QUILL_ASSERT(logger_ptr,
"logger_ptr is nullptr in LoggerManager::create_logger()");
202 "logger is not valid in LoggerManager::create_logger()");
211 template <
typename TLogger>
218 LoggerBase* logger_ptr = _find_logger(logger_name);
222 QUILL_THROW(
QuillError{
"Logger with name \"" + logger_name +
223 "\" is pending removal and cannot be recreated until the backend " 224 "completes logger cleanup. Use remove_logger_blocking() if you need " 225 "to recreate the logger synchronously."});
231 std::unique_ptr<LoggerBase> new_logger{
232 new TLogger{logger_name,
static_cast<std::vector<std::shared_ptr<Sink>
>&&>(sinks),
233 pattern_formatter_options, clock_source, user_clock}};
235 _insert_logger(
static_cast<std::unique_ptr<LoggerBase>&&
>(new_logger));
240 logger_ptr = _find_logger(logger_name);
242 if (logger_ptr && _env_log_level)
248 QUILL_ASSERT(logger_ptr,
"logger_ptr is nullptr in LoggerManager::get_logger()");
250 "logger is not valid in LoggerManager::get_logger()");
255 template <
typename TLogger>
260 return get_logger(logger_name);
263 return create_or_get_logger<TLogger>(logger_name, source_logger->_sinks, source_logger->_pattern_formatter_options,
264 source_logger->_clock_source, source_logger->_user_clock);
271 _has_invalidated_loggers.store(
true, std::memory_order_release);
275 template <
typename TCheckQueuesEmpty>
276 void cleanup_invalidated_loggers(TCheckQueuesEmpty check_queues_empty, std::vector<std::string>& removed_loggers)
278 if (_has_invalidated_loggers.exchange(
false, std::memory_order_acq_rel))
284 std::vector<std::unique_ptr<LoggerBase>> loggers_to_destroy;
288 for (
auto it = _loggers.begin(); it != _loggers.end();)
290 if (!it->get()->is_valid_logger())
293 if (!check_queues_empty())
297 _has_invalidated_loggers.store(
true, std::memory_order_release);
301 removed_loggers.push_back(it->get()->get_logger_name());
302 loggers_to_destroy.push_back(
static_cast<std::unique_ptr<LoggerBase>&&
>(*it));
303 it = _loggers.erase(it);
316 QUILL_NODISCARD
bool has_invalidated_loggers()
const noexcept
318 return _has_invalidated_loggers.load(std::memory_order_acquire);
321 QUILL_ATTRIBUTE_COLD
void parse_log_level_from_env()
323 constexpr
char const* field =
"QUILL_LOG_LEVEL";
325 std::string log_level;
327 #if defined(_MSC_VER) 330 bool const ok = ::getenv_s(&len, buf,
sizeof(buf), field) == 0;
335 #else // revert to getenv 336 char* buf = ::getenv(field);
343 if (!log_level.empty())
345 QUILL_TRY { _env_log_level = loglevel_from_string(log_level); }
346 #if !defined(QUILL_NO_EXCEPTIONS) 352 std::string{
"invalid \"QUILL_LOG_LEVEL\" environment variable value - "} + e.what()});
364 void _insert_logger(std::unique_ptr<LoggerBase> logger)
366 auto search_it = std::lower_bound(_loggers.begin(), _loggers.end(), logger->get_logger_name(),
367 [](std::unique_ptr<LoggerBase>
const& a, std::string
const& b)
368 {
return a->get_logger_name() < b; });
370 _loggers.insert(search_it,
static_cast<std::unique_ptr<LoggerBase>&&
>(logger));
374 QUILL_NODISCARD
LoggerBase* _find_logger(std::string
const& target)
const noexcept
376 auto search_it = std::lower_bound(_loggers.begin(), _loggers.end(), target,
377 [](std::unique_ptr<LoggerBase>
const& a, std::string
const& b)
378 {
return a->get_logger_name() < b; });
380 return (search_it != std::end(_loggers) && search_it->get()->get_logger_name() == target)
386 std::vector<std::unique_ptr<LoggerBase>> _loggers;
387 std::optional<LogLevel> _env_log_level;
389 std::atomic<bool> _has_invalidated_loggers{
false};
Base class for sinks.
Definition: Sink.h:46
QUILL_NODISCARD bool is_valid_logger() const noexcept
Checks if the logger is valid.
Definition: LoggerBase.h:115
void for_each_logger(TCallback cb) const
For backend use only.
Definition: LoggerManager.h:141
Setups a signal handler to handle fatal signals.
Definition: BackendManager.h:28
Definition: Spinlock.h:18
Definition: LoggerBase.h:39
custom exception
Definition: QuillError.h:47
void set_log_level(LogLevel new_log_level)
Set the log level of the logger.
Definition: LoggerBase.h:140
LoggerBase * create_logger(std::string const &logger_name, std::vector< std::shared_ptr< Sink >> sinks, PatternFormatterOptions const &pattern_formatter_options, ClockSourceType clock_source, UserClockSource *user_clock)
Creates a new logger with the given name.
Definition: LoggerManager.h:162
Definition: Spinlock.h:58
LoggerBase * create_or_get_logger(std::string const &logger_name, std::vector< std::shared_ptr< Sink >> sinks, PatternFormatterOptions const &pattern_formatter_options, ClockSourceType clock_source, UserClockSource *user_clock)
Creates a new logger or returns an existing one with the given name.
Definition: LoggerManager.h:212
Base class that provides a timestamp for log statements based on a user-provided clock source...
Definition: UserClockSource.h:27
Definition: LoggerManager.h:39
void mark_invalid()
This function sets the logger's validity flag to false, indicating that the logger is no longer valid...
Definition: LoggerBase.h:109