Compare commits

..
18 Commits
Author SHA256 Message Date
ArchZer0 c3cfc635ee Test 2026-08-20 11:04:58 +08:00
CupWater 27014f192c Merge remote-tracking branch 'origin/main' 2026-08-19 09:00:48 +08:00
CupWater d65184f678 modify something 2026-08-19 09:00:28 +08:00
CupWater 267d7953ba modify something 2026-08-19 09:00:11 +08:00
CupWater c7d4b87d3e modify something 2026-08-18 13:55:04 +08:00
CupWater 693db85e3b modify something 2026-08-18 10:08:52 +08:00
CupWater 4fc7ef37c2 modify something 2026-08-17 21:01:29 +08:00
CupWater 3274bf9393 modify something 2026-08-17 18:52:28 +08:00
CupWater 999f704b67 modify header file 2026-08-17 18:41:32 +08:00
CupWater 2085e9f7a5 add log_outputter.cpp 2026-08-17 18:36:51 +08:00
CupWater 1313cab93e finish log_manager.cpp 2026-08-17 18:27:39 +08:00
CupWater e4d834e4a9 . 2026-08-17 16:09:09 +08:00
CupWater b2aa61dc09 modify log_manager.cpp 2026-08-17 13:49:56 +08:00
CupWater 17d63c62c4 . 2026-08-17 13:47:07 +08:00
CupWater 99404f62d0 . 2026-08-17 13:45:18 +08:00
CupWater 7eb3331d8e . 2026-08-17 13:35:14 +08:00
CupWater b4ed8d601d Merge remote-tracking branch 'origin/main'
# Conflicts:
#	include/featherlog/log_formatter.hpp
2026-08-17 13:29:59 +08:00
CupWater e99541c139 . 2026-08-17 11:31:12 +08:00
16 changed files with 247 additions and 117 deletions
+12 -6
View File
@@ -4,9 +4,9 @@ project(FeatherLog)
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_BINARY_DIR "out") add_compile_definitions(FLOG_IMPL_CONSOLE_OUTPUTTER) # build with default console outputter
add_compile_definitions(FLOG_IMPL_FILE_OUTPUTTER) # build with default file outputter
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/shared") add_compile_definitions(FLOG_IMPL_DEFAULT_FORMATTER) # build with default formatter
# 定义源文件 # 定义源文件
set(${PROJECT_NAME}_SOURCES set(${PROJECT_NAME}_SOURCES
@@ -16,7 +16,14 @@ set(${PROJECT_NAME}_SOURCES
include/featherlog/log_formatter.hpp include/featherlog/log_formatter.hpp
include/featherlog/log_level.hpp include/featherlog/log_level.hpp
include/featherlog/log_message.hpp include/featherlog/log_message.hpp
src/log_manager.cpp) include/featherlog/flog_definitions.h
include/featherlog/push_result.hpp
include/featherlog/log_message_flag.hpp
include/featherlog/featherlog.hpp
src/log_manager.cpp
src/log_message_flag.cpp
include/featherlog/impl/flog_impl.hpp
include/featherlog/impl/console_outputter.hpp)
# 生成静态库 # 生成静态库
add_library(${PROJECT_NAME}_static STATIC ${${PROJECT_NAME}_SOURCES}) add_library(${PROJECT_NAME}_static STATIC ${${PROJECT_NAME}_SOURCES})
@@ -29,8 +36,7 @@ add_compile_definitions(FLOG_DLL_MODE)
add_compile_definitions(FLOG_BUILDING_DLL) add_compile_definitions(FLOG_BUILDING_DLL)
# 生成动态库 # 生成动态库
add_library(${PROJECT_NAME}_shared SHARED ${${PROJECT_NAME}_SOURCES} add_library(${PROJECT_NAME}_shared SHARED ${${PROJECT_NAME}_SOURCES})
include/featherlog/flog_definitions.h)
target_include_directories(${PROJECT_NAME}_shared PUBLIC include) target_include_directories(${PROJECT_NAME}_shared PUBLIC include)
set_target_properties(${PROJECT_NAME}_shared PROPERTIES set_target_properties(${PROJECT_NAME}_shared PROPERTIES
OUTPUT_NAME ${PROJECT_NAME} OUTPUT_NAME ${PROJECT_NAME}
+1
View File
@@ -1,2 +1,3 @@
# FeatherLog # FeatherLog
+16
View File
@@ -0,0 +1,16 @@
#ifndef FEATHERLOG_FEATHERLOG_HPP
#define FEATHERLOG_FEATHERLOG_HPP
#include <featherlog/flog_definitions.h>
#include <featherlog/logger.hpp>
#include <featherlog/log_formatter.hpp>
#include <featherlog/log_level.hpp>
#include <featherlog/log_manager.hpp>
#include <featherlog/log_message.hpp>
#include <featherlog/log_message_flag.hpp>
#include <featherlog/log_outputter.hpp>
#include <featherlog/push_result.hpp>
#include <featherlog/impl/flog_impl.hpp>
#endif
+8
View File
@@ -27,4 +27,12 @@
#endif #endif
#ifndef NODISCARD
# ifdef _NODISCARD
# define NODISCARD _NODISCARD
# else
# define NODISCARD [[nodiscard]]
# endif
#endif
#endif #endif
@@ -0,0 +1,5 @@
#pragma once
#ifdef FLOG_IMPL_CONSOLE_OUTPUTTER
#endif
+7
View File
@@ -0,0 +1,7 @@
#ifndef FEATHERLOG_IMPL_FLOG_IMPL_HPP
#define FEATHERLOG_IMPL_FLOG_IMPL_HPP
#include <featherlog/impl/console_outputter.hpp>
#endif
+5 -8
View File
@@ -1,18 +1,15 @@
#ifndef FEATHERLOG_LOG_FORMATTER_HPP #pragma once
#define FEATHERLOG_LOG_FORMATTER_HPP
#include <string> #include <string>
#include <featherlog/flog_definitions.h>
#include
namespace flog namespace flog
{ {
class LogFormatter class FLOG_API LogFormatter
{ {
public: public:
virtual ~LogFormatter() = default; virtual ~LogFormatter() = default;
virtual std::string format() = 0;
NODISCARD virtual std::string FLOG_CALL format(const LogMessage& message) = 0;
}; };
} }
#endif
+4 -6
View File
@@ -1,11 +1,11 @@
#ifndef FEATHERLOG_LOG_LEVEL_HPP #pragma once
#define FEATHERLOG_LOG_LEVEL_HPP
#include <cstdint> #include <cstdint>
namespace flog namespace flog
{ {
enum class LogLevel : uint8_t using LogLevelType = uint8_t;
enum class LogLevel : LogLevelType
{ {
TRACE = 0, TRACE = 0,
DEBUG = 1, DEBUG = 1,
@@ -14,8 +14,6 @@ namespace flog
ERROR = 4, ERROR = 4,
FATAL = 5, FATAL = 5,
OFF = 0xff, OFF = std::numeric_limits<LogLevelType>::max()
}; };
} }
#endif
+28 -23
View File
@@ -1,59 +1,64 @@
#ifndef FEATHERLOG_LOG_MANAGER_HPP #pragma once
#define FEATHERLOG_LOG_MANAGER_HPP
#include <atomic> #include <atomic>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <shared_mutex> #include <shared_mutex>
#include <unordered_map> #include <unordered_map>
#include <vector>
#include "logger.hpp" #include <featherlog/logger.hpp>
#include "log_formatter.hpp" #include <featherlog/log_level.hpp>
#include "log_level.hpp" #include <featherlog/log_message.hpp>
#include "log_message.hpp" #include <featherlog/log_outputter.hpp>
#include "log_outputter.hpp" #include <featherlog/flog_definitions.h>
#include <featherlog/push_result.hpp>
#include <utility>
namespace flog namespace flog
{ {
class LogManager; class FLOG_API LogManager : public std::enable_shared_from_this<LogManager>
class LogManager : public std::enable_shared_from_this<LogManager>
{ {
friend class LoggerCallback;
public: public:
LogManager(const LogManager &) = delete; LogManager(const LogManager &) = delete;
LogManager &operator=(const LogManager &) = delete; LogManager &operator=(const LogManager &) = delete;
LogManager(LogManager &&) = delete; LogManager(LogManager &&) = delete;
LogManager &operator=(LogManager &&) = delete; LogManager &operator=(LogManager &&) = delete;
static std::shared_ptr<LogManager> create(); NODISCARD static std::shared_ptr<LogManager> FLOG_CALL create() noexcept { return {}; }
NODISCARD static std::shared_ptr<LogManager> FLOG_CALL create(LogMessageFlagManager flagManager);
~LogManager(); ~LogManager();
LogLevel get_min_log_level() const noexcept; NODISCARD LogLevel FLOG_CALL get_min_log_level() const noexcept;
void set_min_log_level(LogLevel level) noexcept; void FLOG_CALL set_min_log_level(LogLevel level) noexcept;
void add_outputter(std::unique_ptr<LogOutputter> outputter); NODISCARD PushResult<std::unique_ptr<LogOutputter>> FLOG_CALL
add_outputter(std::unique_ptr<LogOutputter> outputter);
NODISCARD bool FLOG_CALL contains_outputter(std::string_view name) const;
std::optional<std::unique_ptr<LogOutputter>> FLOG_CALL try_delete_outputter(std::string_view name);
std::shared_ptr<Logger> get_logger(const std::string& name); NODISCARD std::shared_ptr<Logger> FLOG_CALL get_logger(const std::string &name);
size_t clean_unused_loggers(); size_t FLOG_CALL clean_unused_loggers();
private: private:
LogManager() noexcept = default; LogManager() noexcept = default;
void print_log(const LogMessage& message) const; explicit LogManager(LogMessageFlagManager flagManager) noexcept :
m_logMessageFlagManager(std::move(flagManager))
{ }
void FLOG_CALL write_log(const LogMessage &message) const;
std::atomic<LogLevel> m_minLogLevel{LogLevel::DEBUG}; std::atomic<LogLevel> m_minLogLevel{LogLevel::DEBUG};
mutable std::shared_mutex m_logOutputtersMutex; mutable std::shared_mutex m_logOutputtersMutex;
std::vector<std::unique_ptr<LogOutputter>> m_logOutputters; std::unordered_map<std::string, std::unique_ptr<LogOutputter>> m_logOutputters;
mutable std::mutex m_loggersMutex; mutable std::mutex m_loggersMutex;
std::unordered_map<std::string, std::shared_ptr<Logger>> m_loggers; std::unordered_map<std::string, std::shared_ptr<Logger>> m_loggers;
mutable std::shared_mutex m_logMessageFlagManagerMutex;
LogMessageFlagManager m_logMessageFlagManager;
}; };
} }
#endif
+7 -8
View File
@@ -1,20 +1,19 @@
#ifndef FEATHERLOG_LOG_MESSAGE_HPP #pragma once
#define FEATHERLOG_LOG_MESSAGE_HPP
#include <chrono> #include <chrono>
#include <string_view> #include <string_view>
#include "log_level.hpp" #include <featherlog/log_level.hpp>
#include <featherlog/log_message_flag.hpp>
namespace flog namespace flog
{ {
struct LogMessage { struct LogMessage
{
std::chrono::system_clock::time_point timestamp; std::chrono::system_clock::time_point timestamp;
LogLevel level;
std::string_view logger_name; std::string_view logger_name;
std::string text; std::string text;
LogLevel level;
MessageFlag flag;
}; };
} }
#endif
+40
View File
@@ -0,0 +1,40 @@
#pragma once
#include <array>
#include <limits>
namespace flog
{
typedef uint32_t LogMessageFlag;
typedef LogMessageFlag MessageFlag;
typedef class LogMessageFlagManager
{
public:
static constexpr MessageFlag ADD_FAILED = 0;
static constexpr size_t FLAG_ARRAY_SIZE = std::numeric_limits<MessageFlag>::digits;
LogMessageFlagManager() noexcept = default;
~LogMessageFlagManager() = default;
LogMessageFlagManager(const LogMessageFlagManager&) noexcept = default;
LogMessageFlagManager& operator=(const LogMessageFlagManager&) noexcept = default;
LogMessageFlagManager(LogMessageFlagManager&&) noexcept = default;
LogMessageFlagManager& operator=(LogMessageFlagManager&&) noexcept = default;
NODISCARD bool isFull() const noexcept { return flagCount >= FLAG_ARRAY_SIZE; }
NODISCARD bool pushable() const noexcept { return !isFull(); }
NODISCARD bool isEmpty() const noexcept { return flagCount == 0; }
NODISCARD bool empty() const noexcept { return isEmpty(); }
NODISCARD bool contains(std::string_view name) const noexcept;
NODISCARD MessageFlag addFlag (std::string_view name);
NODISCARD MessageFlag findFlag(std::string_view name) const;
private:
std::array<std::string, FLAG_ARRAY_SIZE> m_flagMap{};
size_t flagCount { 0 };
} MessageFlagManager;
}
+16 -10
View File
@@ -1,26 +1,32 @@
#ifndef FEATHERLOG_LOG_OUTPUTTER_HPP #pragma once
#define FEATHERLOG_LOG_OUTPUTTER_HPP
#include <memory> #include <memory>
#include "log_formatter.hpp" #include <featherlog/log_formatter.hpp>
#include "log_message.hpp" #include <featherlog/log_message.hpp>
#include <featherlog/flog_definitions.h>
namespace flog namespace flog
{ {
class LogOutputter class FLOG_API LogOutputter
{ {
public: public:
LogOutputter(std::string name, std::unique_ptr<LogFormatter> formatter) noexcept
: m_name(std::move(name)), m_logFormatter(std::move(formatter))
{ }
virtual ~LogOutputter() = default; virtual ~LogOutputter() = default;
std::unique_ptr<LogFormatter> set_formatter(const std::unique_ptr<LogFormatter>& formatter); NODISCARD std::string FLOG_CALL getName() const noexcept { return m_name; }
std::unique_ptr<LogFormatter>& get_formatter();
virtual void write(const LogMessage& message) = 0; std::unique_ptr<LogFormatter> FLOG_CALL set_formatter(const std::unique_ptr<LogFormatter> &formatter);
NODISCARD const std::unique_ptr<LogFormatter> & FLOG_CALL get_formatter() const;
virtual void FLOG_CALL write_log(const LogMessage &message) = 0;
protected: protected:
const std::string m_name;
std::unique_ptr<LogFormatter> m_logFormatter; std::unique_ptr<LogFormatter> m_logFormatter;
}; };
} }
#endif
+15 -11
View File
@@ -1,33 +1,37 @@
#ifndef FEATHERLOG_LOGGER_HPP #pragma once
#define FEATHERLOG_LOGGER_HPP
#include <format> #include <format>
#include <source_location> #include <source_location>
#include <utility>
#include "log_manager.hpp" #include <featherlog/flog_definitions.h>
namespace flog namespace flog
{ {
class LoggerCallback; class LogManager;
class Logger class FLOG_API Logger final
{ {
friend class LogManager; friend class LogManager;
public: public:
Logger(const Logger&) = delete;
Logger operator=(const Logger&) = delete;
Logger(const Logger&&) = delete;
Logger operator=(const Logger&&) = delete;
~Logger() = default; ~Logger() = default;
template<typename... Args> template<typename... Args>
void info(std::format_string<Args...> fmt, Args&&... args, void FLOG_CALL info(std::format_string<Args...> fmt, Args &&... args,
std::source_location loc = std::source_location::current()); std::source_location loc = std::source_location::current());
private: private:
Logger(const std::string& name, std::weak_ptr<LogManager> manager) : m_name(name), m_logManager(manager) Logger(std::string name, const std::weak_ptr<LogManager> &manager) noexcept : m_name(std::move(name)),
m_logManager(manager)
{ } { }
std::string m_name; const std::string m_name;
std::weak_ptr<LogManager> m_logManager; const std::weak_ptr<LogManager> m_logManager;
}; };
} }
#endif
+38
View File
@@ -0,0 +1,38 @@
#pragma once
#include <optional>
#include <functional>
namespace flog
{
template <typename T>
class PushResult
{
public:
NODISCARD static PushResult success() noexcept { return PushResult(); }
NODISCARD static PushResult failWithValue(T value) noexcept
{
return PushResult(std::move(std::optional<T>(std::move(value))));
}
NODISCARD bool isSuccessful() const noexcept { return !m_value.has_value(); }
NODISCARD bool isFail() const noexcept { return m_value.has_value(); }
void getValueIfFail(const std::function<void(const T& value)> func) const
{
if (isFail()) {
func(m_value.value());
}
}
NODISCARD T getValue() const { return m_value.value(); }
PushResult(const PushResult &other) noexcept { m_value = other.m_value; }
private:
PushResult() noexcept = default;
explicit PushResult(std::optional<T> value) noexcept : m_value(std::move(value)) {}
const std::optional<T> m_value = std::nullopt;
};
}
+38 -39
View File
@@ -1,16 +1,13 @@
#include "../include/featherlog/log_manager.hpp" #include <featherlog/log_manager.hpp>
#include <featherlog/push_result.hpp>
namespace flog namespace flog
{ {
std::shared_ptr<LogManager> LogManager::create(MessageFlagManager flagManager) {
return std::shared_ptr<LogManager>(new LogManager(std::move(flagManager)));
inline std::shared_ptr<LogManager> LogManager::create()
{
// ReSharper disable once CppDFAMemoryLeak
return std::shared_ptr<LogManager>(new LogManager());
} }
inline LogManager::~LogManager() LogManager::~LogManager()
{ {
{ {
std::lock_guard lock(m_loggersMutex); std::lock_guard lock(m_loggersMutex);
@@ -22,23 +19,47 @@ namespace flog
} }
} }
inline LogLevel LogManager::get_min_log_level() const noexcept LogLevel LogManager::get_min_log_level() const noexcept
{ {
return m_minLogLevel.load(std::memory_order_relaxed); return m_minLogLevel.load(std::memory_order_relaxed);
} }
inline void LogManager::set_min_log_level(const LogLevel level) noexcept void LogManager::set_min_log_level(const LogLevel level) noexcept
{ {
m_minLogLevel.store(level, std::memory_order_relaxed); m_minLogLevel.store(level, std::memory_order_relaxed);
} }
inline void LogManager::add_outputter(std::unique_ptr<LogOutputter> outputter) PushResult<std::unique_ptr<LogOutputter>> LogManager::add_outputter(std::unique_ptr<LogOutputter> outputter)
{ {
std::lock_guard lock(m_logOutputtersMutex); std::lock_guard lock(m_logOutputtersMutex);
m_logOutputters.push_back(std::move(outputter)); if (m_logOutputters.contains(outputter->getName()))
{
return PushResult<std::unique_ptr<LogOutputter>>::failWithValue(std::move(outputter));
}
m_logOutputters.emplace(outputter->getName(), std::move(outputter));
return PushResult<std::unique_ptr<LogOutputter>>::success();
} }
inline std::shared_ptr<Logger> LogManager::get_logger(const std::string& name) bool LogManager::contains_outputter(const std::string_view name) const
{
std::shared_lock lock(m_logOutputtersMutex);
return m_logOutputters.contains(name.data());
}
std::optional<std::unique_ptr<LogOutputter>> LogManager::try_delete_outputter(const std::string_view name)
{
if (contains_outputter(name))
{
std::lock_guard lock(m_logOutputtersMutex);
const auto it = m_logOutputters.find(name.data());
std::optional outputter = std::move(it->second);
m_logOutputters.erase(it);
return std::move(outputter);
}
return std::nullopt;
}
std::shared_ptr<Logger> LogManager::get_logger(const std::string &name)
{ {
std::lock_guard lock(m_loggersMutex); std::lock_guard lock(m_loggersMutex);
if (const auto it = m_loggers.find(name); it != m_loggers.end()) if (const auto it = m_loggers.find(name); it != m_loggers.end())
@@ -51,7 +72,7 @@ namespace flog
return logger; return logger;
} }
inline size_t LogManager::clean_unused_loggers() size_t LogManager::clean_unused_loggers()
{ {
std::lock_guard lock(m_loggersMutex); std::lock_guard lock(m_loggersMutex);
size_t count = 0; size_t count = 0;
@@ -70,34 +91,12 @@ namespace flog
return count; return count;
} }
inline void LogManager::print_log(const LogMessage& message) const void LogManager::write_log(const LogMessage &message) const
{ {
std::shared_lock lock(m_logOutputtersMutex); std::shared_lock lock(m_logOutputtersMutex);
for (auto& outputter : m_logOutputters) for (const std::unique_ptr<LogOutputter> &outputter: m_logOutputters | std::views::values)
{ {
outputter->write(message); outputter->write_log(message);
} }
} }
inline LoggerCallback::LoggerCallback(const std::weak_ptr<LogManager>& logManager) noexcept : m_logManager(
logManager)
{
}
inline void LoggerCallback::print_log(const LogMessage& message) const
{
if (const auto mgr = m_logManager.lock())
{
mgr->print_log(message);
}
}
inline LogLevel LoggerCallback::get_min_log_level() const noexcept
{
if (const auto mgr = m_logManager.lock())
{
return mgr->get_min_log_level();
}
return LogLevel::OFF;
}
} }
+1
View File
@@ -0,0 +1 @@
#include <featherlog/log_message_flag.hpp>