V2.x no reg (#3285)

Removed registry
This commit is contained in:
Gabi Melman
2024-12-06 19:21:42 +02:00
committed by GitHub
parent ed6919bf8e
commit 166843ff3a
52 changed files with 308 additions and 1336 deletions

View File

@@ -1,99 +0,0 @@
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#include "spdlog/cfg/helpers.h"
#include <algorithm>
#include <sstream>
#include <string>
#include <utility>
#include "spdlog/details/registry.h"
namespace spdlog {
namespace cfg {
namespace helpers {
// inplace convert to lowercase
inline std::string &to_lower_(std::string &str) {
std::transform(str.begin(), str.end(), str.begin(),
[](char ch) { return static_cast<char>((ch >= 'A' && ch <= 'Z') ? ch + ('a' - 'A') : ch); });
return str;
}
// inplace trim spaces
inline std::string &trim_(std::string &str) {
const char *spaces = " \n\r\t";
str.erase(str.find_last_not_of(spaces) + 1);
str.erase(0, str.find_first_not_of(spaces));
return str;
}
// return (name,value) trimmed pair from given "name=value" string.
// return empty string on missing parts
// "key=val" => ("key", "val")
// " key = val " => ("key", "val")
// "key=" => ("key", "")
// "val" => ("", "val")
inline std::pair<std::string, std::string> extract_kv_(char sep, const std::string &str) {
auto n = str.find(sep);
std::string k, v;
if (n == std::string::npos) {
v = str;
} else {
k = str.substr(0, n);
v = str.substr(n + 1);
}
return std::make_pair(trim_(k), trim_(v));
}
// return vector of key/value pairs from sequence of "K1=V1,K2=V2,.."
// "a=AAA,b=BBB,c=CCC,.." => {("a","AAA"),("b","BBB"),("c", "CCC"),...}
inline std::unordered_map<std::string, std::string> extract_key_vals_(const std::string &str) {
std::string token;
std::istringstream token_stream(str);
std::unordered_map<std::string, std::string> rv{};
while (std::getline(token_stream, token, ',')) {
if (token.empty()) {
continue;
}
auto kv = extract_kv_('=', token);
rv[kv.first] = kv.second;
}
return rv;
}
void load_levels(const std::string &input) {
if (input.empty() || input.size() > 512) {
return;
}
auto key_vals = extract_key_vals_(input);
std::unordered_map<std::string, level> levels;
level global_level = level::info;
bool global_level_found = false;
for (auto &name_level : key_vals) {
const auto &logger_name = name_level.first;
auto level_name = to_lower_(name_level.second);
auto level = level_from_str(level_name);
// ignore unrecognized level names
if (level == level::off && level_name != "off") {
continue;
}
if (logger_name.empty()) // no logger name indicate global level
{
global_level_found = true;
global_level = level;
} else {
levels[logger_name] = level;
}
}
details::registry::instance().set_levels(std::move(levels), global_level_found ? &global_level : nullptr);
}
} // namespace helpers
} // namespace cfg
} // namespace spdlog

49
src/details/context.cpp Normal file
View File

@@ -0,0 +1,49 @@
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#include "spdlog/details/context.h"
#include "spdlog/logger.h"
#ifndef SPDLOG_DISABLE_GLOBAL_LOGGER
#include "spdlog/sinks/stdout_color_sinks.h"
#endif // SPDLOG_DISABLE_GLOBAL_LOGGER
#include <memory>
namespace spdlog {
namespace details {
context::context(std::unique_ptr<logger> global_logger) { global_logger_ = std::move(global_logger); }
std::shared_ptr<logger> context::global_logger() { return global_logger_; }
// Return raw ptr to the global logger.
// To be used directly by the spdlog default api (e.g. spdlog::info)
// This make the default API faster, but cannot be used concurrently with set_global_logger().
// e.g do not call set_global_logger() from one thread while calling spdlog::info() from another.
logger *context::global_logger_raw() const noexcept { return global_logger_.get(); }
// set global logger
void context::set_logger(std::shared_ptr<logger> new_global_logger) { global_logger_ = std::move(new_global_logger); }
void context::set_tp(std::shared_ptr<thread_pool> tp) {
std::lock_guard lock(tp_mutex_);
tp_ = std::move(tp);
}
std::shared_ptr<thread_pool> context::get_tp() {
std::lock_guard lock(tp_mutex_);
return tp_;
}
// clean all resources and threads started by the registry
void context::shutdown() {
std::lock_guard lock(tp_mutex_);
tp_.reset();
}
std::recursive_mutex &context::tp_mutex() { return tp_mutex_; }
} // namespace details
} // namespace spdlog

View File

@@ -1,13 +1,13 @@
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#include "spdlog/details/file_helper.h"
#include <cerrno>
#include <cstdio>
#include <utility>
#include <filesystem>
#include <utility>
#include "spdlog/details/file_helper.h"
#include "spdlog/common.h"
#include "spdlog/details/os.h"
@@ -29,9 +29,11 @@ void file_helper::open(const filename_t &fname, bool truncate) {
if (event_handlers_.before_open) {
event_handlers_.before_open(filename_);
}
// create containing folder if not exists already.
os::create_dir(os::dir_name(fname));
for (int tries = 0; tries < open_tries_; ++tries) {
// create containing folder if not exists already.
os::create_dir(os::dir_name(fname));
if (truncate) {
// Truncate by opening-and-closing a tmp file in "wb" mode, always
// opening the actual log-we-write-to in "ab" mode, since that
@@ -108,6 +110,5 @@ size_t file_helper::size() const {
const filename_t &file_helper::filename() const { return filename_; }
} // namespace details
} // namespace spdlog

View File

@@ -11,9 +11,7 @@ namespace spdlog {
namespace details {
namespace os {
bool remove(const filename_t &filename) {
return std::filesystem::remove(filename);
}
bool remove(const filename_t &filename) { return std::filesystem::remove(filename); }
bool remove_if_exists(const filename_t &filename) {
if (path_exists(filename)) {
@@ -42,7 +40,6 @@ bool path_exists(const filename_t &filename) noexcept { return std::filesystem::
// "abc///" => "abc//"
filename_t dir_name(const filename_t &path) { return path.parent_path(); }
// Create the given directory - and all directories leading to it
// return true on success or if the directory already exists
bool create_dir(const filename_t &path) {
@@ -50,19 +47,13 @@ bool create_dir(const filename_t &path) {
return std::filesystem::create_directories(path, ec) || !ec;
}
// Return file path and its extension:
//
// "mylog.txt" => ("mylog", ".txt")
// "mylog" => ("mylog", "")
// "mylog." => ("mylog", ".")
// "/dir1/dir2/mylog.txt" => ("/dir1/dir2/mylog", ".txt")
//
// the starting dot in filenames is ignored (hidden files):
//
// ".mylog" => (".mylog". "")
// "my_folder/.mylog" => ("my_folder/.mylog", "")
// "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt")
// ".mylog" => (".mylog", "")
std::tuple<filename_t, filename_t> split_by_extension(const filename_t &fname) {
const auto ext = fname.extension();
auto without_ext = filename_t(fname).replace_extension();

View File

@@ -99,7 +99,6 @@ bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode) {
return *fp == nullptr;
}
// Return file size according to open FILE* object
size_t filesize(FILE *f) {
if (f == nullptr) {
@@ -231,9 +230,9 @@ void sleep_for_millis(unsigned int milliseconds) noexcept {
std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
}
std::string filename_to_str(const filename_t &filename) {
std::string filename_to_str(const filename_t &filename) {
static_assert(std::is_same_v<filename_t::value_type, char>, "filename_t type must be char");
return filename;
return filename;
}
int pid() noexcept { return static_cast<int>(::getpid()); }

View File

@@ -6,7 +6,7 @@
#endif
// clang-format off
#include "spdlog/details/windows_include.h"
#include "spdlog/details/windows_include.h" // must be included before fileapi.h etc.
// clang-format on
#include <fileapi.h> // for FlushFileBuffers
@@ -75,8 +75,6 @@ bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode) {
return *fp == nullptr;
}
#ifdef _MSC_VER
// avoid warning about unreachable statement at the end of filesize()
#pragma warning(push)
@@ -151,15 +149,13 @@ void sleep_for_millis(unsigned int milliseconds) noexcept { ::Sleep(milliseconds
// Try tp convert wstring filename to string. Return "???" if failed
std::string filename_to_str(const filename_t &filename) {
static_assert(std::is_same_v<filename_t::value_type, wchar_t>, "filename_t type must be wchar_t");
try {
try {
memory_buf_t buf;
wstr_to_utf8buf(filename.wstring(), buf);
return std::string(buf.data(), buf.size());
} catch (...) {
return "???";
}
catch (...) {
return "???";
}
}
int pid() noexcept { return static_cast<int>(::GetCurrentProcessId()); }
@@ -224,7 +220,6 @@ void utf8_to_wstrbuf(string_view_t str, wmemory_buf_t &target) {
throw_spdlog_ex(fmt_lib::format("MultiByteToWideChar failed. Last error: {}", ::GetLastError()));
}
std::string getenv(const char *field) {
#if defined(_MSC_VER)
#if defined(__cplusplus_winrt)

View File

@@ -1,22 +0,0 @@
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#include "spdlog/details/periodic_worker.h"
namespace spdlog {
namespace details {
// stop the worker thread and join it
periodic_worker::~periodic_worker() {
if (worker_thread_.joinable()) {
{
std::lock_guard<std::mutex> lock(mutex_);
active_ = false;
}
cv_.notify_one();
worker_thread_.join();
}
}
} // namespace details
} // namespace spdlog

View File

@@ -1,263 +0,0 @@
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
#include "spdlog/details/registry.h"
#include "spdlog/common.h"
#include "spdlog/logger.h"
#include "spdlog/pattern_formatter.h"
#ifndef SPDLOG_DISABLE_DEFAULT_LOGGER
// support for the default stdout color logger
#ifdef _WIN32
#include "spdlog/sinks/wincolor_sink.h"
#else
#include "spdlog/sinks/ansicolor_sink.h"
#endif
#endif // SPDLOG_DISABLE_DEFAULT_LOGGER
#include <memory>
#include <string>
#include <unordered_map>
static constexpr size_t small_map_threshold = 10;
namespace spdlog {
namespace details {
registry::registry()
: formatter_(new pattern_formatter()) {
#ifndef SPDLOG_DISABLE_DEFAULT_LOGGER
// create default logger (ansicolor_stdout_sink_mt or wincolor_stdout_sink_mt in windows).
#ifdef _WIN32
auto color_sink = std::make_shared<sinks::wincolor_stdout_sink_mt>();
#else
auto color_sink = std::make_shared<sinks::ansicolor_stdout_sink_mt>();
#endif
const char *default_logger_name = "";
default_logger_ = std::make_shared<spdlog::logger>(default_logger_name, std::move(color_sink));
loggers_[default_logger_name] = default_logger_;
#endif // SPDLOG_DISABLE_DEFAULT_LOGGER
}
registry::~registry() = default;
void registry::register_logger(std::shared_ptr<logger> new_logger) {
std::lock_guard<std::mutex> lock(logger_map_mutex_);
register_logger_(std::move(new_logger));
}
void registry::initialize_logger(std::shared_ptr<logger> new_logger) {
std::lock_guard<std::mutex> lock(logger_map_mutex_);
new_logger->set_formatter(formatter_->clone());
if (err_handler_) {
new_logger->set_error_handler(err_handler_);
}
// set new level according to previously configured level or default level
auto it = log_levels_.find(new_logger->name());
auto new_level = it != log_levels_.end() ? it->second : global_log_level_;
new_logger->set_level(new_level);
new_logger->flush_on(flush_level_);
if (automatic_registration_) {
register_logger_(std::move(new_logger));
}
}
// if the map is small do a sequential search, otherwise use the standard find()
std::shared_ptr<logger> registry::get(const std::string &logger_name) {
std::lock_guard<std::mutex> lock(logger_map_mutex_);
if (loggers_.size() <= small_map_threshold) {
for (const auto &[key, val] : loggers_) {
if (logger_name == key) {
return val;
}
}
return nullptr;
}
auto found = loggers_.find(logger_name);
return found == loggers_.end() ? nullptr : found->second;
}
// if the map is small do a sequential search and avoid creating string for find(logger_name)
// otherwise use the standard find()
std::shared_ptr<logger> registry::get(std::string_view logger_name) {
std::lock_guard<std::mutex> lock(logger_map_mutex_);
if (loggers_.size() <= small_map_threshold) {
for (const auto &[key, val] : loggers_) {
if (logger_name == key) {
return val;
}
}
return nullptr;
}
// otherwise use the normal map lookup
const auto found = loggers_.find(std::string(logger_name));
return found == loggers_.end() ? nullptr : found->second;
}
std::shared_ptr<logger> registry::get(const char *logger_name) { return get(std::string_view(logger_name)); }
std::shared_ptr<logger> registry::default_logger() {
std::lock_guard<std::mutex> lock(logger_map_mutex_);
return default_logger_;
}
// Return raw ptr to the default logger.
// To be used directly by the spdlog default api (e.g. spdlog::info)
// This make the default API faster, but cannot be used concurrently with set_default_logger().
// e.g do not call set_default_logger() from one thread while calling spdlog::info() from another.
logger *registry::get_default_raw() const { return default_logger_.get(); }
// set default logger.
// default logger is stored in default_logger_ (for faster retrieval) and in the loggers_ map.
void registry::set_default_logger(std::shared_ptr<logger> new_default_logger) {
std::lock_guard<std::mutex> lock(logger_map_mutex_);
if (new_default_logger != nullptr) {
loggers_[new_default_logger->name()] = new_default_logger;
}
default_logger_ = std::move(new_default_logger);
}
void registry::set_tp(std::shared_ptr<thread_pool> tp) {
std::lock_guard<std::recursive_mutex> lock(tp_mutex_);
tp_ = std::move(tp);
}
std::shared_ptr<thread_pool> registry::get_tp() {
std::lock_guard<std::recursive_mutex> lock(tp_mutex_);
return tp_;
}
// Set global formatter. Each sink in each logger will get a clone of this object
void registry::set_formatter(std::unique_ptr<formatter> formatter) {
std::lock_guard<std::mutex> lock(logger_map_mutex_);
formatter_ = std::move(formatter);
for (auto &l : loggers_) {
l.second->set_formatter(formatter_->clone());
}
}
void registry::set_level(level level) {
std::lock_guard<std::mutex> lock(logger_map_mutex_);
for (auto &l : loggers_) {
l.second->set_level(level);
}
global_log_level_ = level;
}
void registry::flush_on(level level) {
std::lock_guard<std::mutex> lock(logger_map_mutex_);
for (auto &l : loggers_) {
l.second->flush_on(level);
}
flush_level_ = level;
}
void registry::set_error_handler(err_handler handler) {
std::lock_guard<std::mutex> lock(logger_map_mutex_);
for (auto &l : loggers_) {
l.second->set_error_handler(handler);
}
err_handler_ = std::move(handler);
}
void registry::apply_all(const std::function<void(const std::shared_ptr<logger>)> &fun) {
std::lock_guard<std::mutex> lock(logger_map_mutex_);
for (auto &l : loggers_) {
fun(l.second);
}
}
void registry::flush_all() {
std::lock_guard<std::mutex> lock(logger_map_mutex_);
for (auto &l : loggers_) {
l.second->flush();
}
}
void registry::drop(const std::string &logger_name) {
std::lock_guard<std::mutex> lock(logger_map_mutex_);
auto is_default_logger = default_logger_ && default_logger_->name() == logger_name;
loggers_.erase(logger_name);
if (is_default_logger) {
default_logger_.reset();
}
}
void registry::drop_all() {
std::lock_guard<std::mutex> lock(logger_map_mutex_);
loggers_.clear();
default_logger_.reset();
}
// clean all resources and threads started by the registry
void registry::shutdown() {
{
std::lock_guard<std::mutex> lock(flusher_mutex_);
periodic_flusher_.reset();
}
drop_all();
{
std::lock_guard<std::recursive_mutex> lock(tp_mutex_);
tp_.reset();
}
}
std::recursive_mutex &registry::tp_mutex() { return tp_mutex_; }
void registry::set_automatic_registration(bool automatic_registration) {
std::lock_guard<std::mutex> lock(logger_map_mutex_);
automatic_registration_ = automatic_registration;
}
void registry::set_levels(log_levels levels, level *global_level) {
std::lock_guard<std::mutex> lock(logger_map_mutex_);
log_levels_ = std::move(levels);
auto global_level_requested = global_level != nullptr;
global_log_level_ = global_level_requested ? *global_level : global_log_level_;
for (auto &logger : loggers_) {
auto logger_entry = log_levels_.find(logger.first);
if (logger_entry != log_levels_.end()) {
logger.second->set_level(logger_entry->second);
} else if (global_level_requested) {
logger.second->set_level(*global_level);
}
}
}
registry &registry::instance() {
static registry s_instance;
return s_instance;
}
void registry::apply_logger_env_levels(std::shared_ptr<logger> new_logger) {
std::lock_guard<std::mutex> lock(logger_map_mutex_);
auto it = log_levels_.find(new_logger->name());
auto new_level = it != log_levels_.end() ? it->second : global_log_level_;
new_logger->set_level(new_level);
}
void registry::throw_if_exists_(const std::string &logger_name) {
if (loggers_.find(logger_name) != loggers_.end()) {
throw_spdlog_ex("logger with name '" + logger_name + "' already exists");
}
}
void registry::register_logger_(std::shared_ptr<logger> new_logger) {
auto logger_name = new_logger->name();
throw_if_exists_(logger_name);
loggers_[logger_name] = std::move(new_logger);
}
} // namespace details
} // namespace spdlog

View File

@@ -5,9 +5,9 @@
#include <cerrno>
#include <mutex>
#include <sstream>
#include <string>
#include <tuple>
#include <sstream>
#include "spdlog/common.h"
#include "spdlog/details/file_helper.h"
@@ -51,10 +51,10 @@ filename_t rotating_file_sink<Mutex>::calc_filename(const filename_t &filename,
filename_t basename;
filename_t ext;
std::tie(basename, ext) = details::os::split_by_extension(filename);
std::tie(basename, ext) = details::os::split_by_extension(filename);
std::basic_ostringstream<filename_t::value_type> oss;
oss << basename.native() << '.' << index << ext.native();
return oss.str();
return oss.str();
}
template <typename Mutex>
@@ -132,7 +132,7 @@ void rotating_file_sink<Mutex>::rotate_() {
// delete the target if exists, and rename the src file to target
// return true on success, false otherwise.
template <typename Mutex>
bool rotating_file_sink<Mutex>::rename_file_(const filename_t &src_filename, const filename_t &target_filename) noexcept{
bool rotating_file_sink<Mutex>::rename_file_(const filename_t &src_filename, const filename_t &target_filename) noexcept {
return details::os::rename(src_filename, target_filename);
}

View File

@@ -3,6 +3,7 @@
#include "spdlog/spdlog.h"
#include <cassert>
#include <memory>
#include "spdlog/common.h"
@@ -12,55 +13,45 @@
namespace spdlog {
void initialize_logger(std::shared_ptr<logger> logger) { details::registry::instance().initialize_logger(std::move(logger)); }
static std::shared_ptr s_context =
#ifndef SPDLOG_DISABLE_GLOBAL_LOGGER
std::make_unique<details::context>(std::make_unique<logger>(std::string(), std::make_unique<sinks::stdout_color_sink_mt>()));
#else
std::make_unique<details::context>(); // empty context
#endif
std::shared_ptr<logger> get(const std::string &name) { return details::registry::instance().get(name); }
void set_context(std::shared_ptr<details::context> context) { s_context = std::move(context); }
std::shared_ptr<logger> get(std::string_view name) { return details::registry::instance().get(name); }
std::shared_ptr<details::context> context() { return s_context; }
std::shared_ptr<logger> get(const char *name) { return details::registry::instance().get(name); }
const std::shared_ptr<details::context> &context_ref() { return s_context; }
void set_formatter(std::unique_ptr<spdlog::formatter> formatter) {
details::registry::instance().set_formatter(std::move(formatter));
std::shared_ptr<logger> global_logger() { return context_ref()->global_logger(); }
void set_global_logger(std::shared_ptr<logger> global_logger) { context()->set_logger(std::move(global_logger)); }
logger *global_logger_raw() noexcept {
auto *rv = context_ref()->global_logger_raw();
assert(rv != nullptr);
return rv;
}
void set_formatter(std::unique_ptr<formatter> formatter) { global_logger()->set_formatter(std::move(formatter)); }
void set_pattern(std::string pattern, pattern_time_type time_type) {
set_formatter(std::make_unique<spdlog::pattern_formatter>(std::move(pattern), time_type));
set_formatter(std::make_unique<pattern_formatter>(std::move(pattern), time_type));
}
level get_level() { return default_logger_raw()->log_level(); }
level get_level() { return global_logger()->log_level(); }
bool should_log(level level) { return default_logger_raw()->should_log(level); }
bool should_log(level level) { return global_logger()->should_log(level); }
void set_level(level level) { details::registry::instance().set_level(level); }
void set_level(level level) { global_logger()->set_level(level); }
void flush_on(level level) { details::registry::instance().flush_on(level); }
void flush_on(level level) { global_logger()->flush_on(level); }
void set_error_handler(void (*handler)(const std::string &msg)) { details::registry::instance().set_error_handler(handler); }
void set_error_handler(void (*handler)(const std::string &msg)) { global_logger()->set_error_handler(handler); }
void register_logger(std::shared_ptr<logger> logger) { details::registry::instance().register_logger(std::move(logger)); }
void shutdown() { s_context.reset(); }
void apply_all(const std::function<void(std::shared_ptr<logger>)> &fun) { details::registry::instance().apply_all(fun); }
void drop(const std::string &name) { details::registry::instance().drop(name); }
void drop_all() { details::registry::instance().drop_all(); }
void shutdown() { details::registry::instance().shutdown(); }
void set_automatic_registration(bool automatic_registration) {
details::registry::instance().set_automatic_registration(automatic_registration);
}
std::shared_ptr<spdlog::logger> default_logger() { return details::registry::instance().default_logger(); }
spdlog::logger *default_logger_raw() { return details::registry::instance().get_default_raw(); }
void set_default_logger(std::shared_ptr<spdlog::logger> default_logger) {
details::registry::instance().set_default_logger(std::move(default_logger));
}
void apply_logger_env_levels(std::shared_ptr<logger> logger) {
details::registry::instance().apply_logger_env_levels(std::move(logger));
}
} // namespace spdlog