Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Support for line ending normalization
- `Kappa::Logger::SetLevel` to dynamically adjust logging verbosity
- `Kappa::LogLevel` enum for type-safe log level management
- Refactored `Kappa::Logger` using PIMPL pattern to hide `spdlog` implementation details from public API
- CMake presets for easier configuration

### Changed

Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ find_package(spdlog CONFIG REQUIRED)

add_library(Kappa STATIC
src/Application.cpp
src/Logger.cpp
src/Window.cpp
src/WindowStatePersistence.cpp
src/Texture.cpp)
Expand Down
102 changes: 102 additions & 0 deletions CMakePresets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
{
"version": 6,
"cmakeMinimumRequired": {
"major": 3,
"minor": 25,
"patch": 0
},
"configurePresets": [
{
"name": "base",
"hidden": true,
"binaryDir": "${sourceDir}/build/${presetName}"
},
{
"name": "native-base",
"hidden": true,
"inherits": "base",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": {
"value": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
"type": "FILEPATH"
}
}
},
{
"name": "single-config-base",
"hidden": true,
"inherits": "native-base",
"generator": "Ninja"
},
{
"name": "multi-config-base",
"hidden": true,
"inherits": "native-base",
"generator": "Visual Studio 17 2022",
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
}
},
{
"name": "ninja-debug",
"displayName": "Ninja Debug",
"inherits": "single-config-base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"SH3DS_ENABLE_SANITIZERS": "OFF"
}
},
{
"name": "ninja-release",
"displayName": "Ninja Release",
"inherits": "single-config-base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"name": "visual-studio",
"displayName": "Visual Studio",
"inherits": "multi-config-base"
}
],
"buildPresets": [
{
"name": "ninja-debug",
"configurePreset": "ninja-debug"
},
{
"name": "ninja-release",
"configurePreset": "ninja-release"
},
{
"name": "visual-studio-debug",
"configurePreset": "visual-studio",
"configuration": "Debug"
},
{
"name": "visual-studio-release",
"configurePreset": "visual-studio",
"configuration": "Release"
}
],
"testPresets": [
{
"name": "ninja-debug",
"configurePreset": "ninja-debug",
"output": {
"outputOnFailure": true
}
},
{
"name": "visual-studio-debug",
"configurePreset": "visual-studio",
"configuration": "Debug",
"output": {
"outputOnFailure": true
}
}
]
}
137 changes: 43 additions & 94 deletions include/Kappa/Logger.h
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
#pragma once

#include <chrono>
#include <format>
#include <memory>
#include <source_location>

#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/spdlog.h>
#include <string>
#include <string_view>

namespace Kappa
{
/**
* @brief Logging levels.
*/
enum class LogLevel
{
Trace = 0,
Debug = 1,
Info = 2,
Warn = 3,
Error = 4,
Critical = 5,
Off = 6
};

/**
* @brief Type-safe logging wrapper around spdlog.
*/
Expand All @@ -20,31 +32,13 @@ namespace Kappa
* @brief Returns the logger instance.
* @return Logger instance
*/
static Logger &Get()
{
static Logger instance(spdlog::stdout_color_mt(GetLoggerName()));
return instance;
}
static Logger &Get();

/**
* @brief Sets the logger name (must be called before first Get()).
* @param name Logger name to display in logs
*/
static void SetLoggerName(const std::string &name)
{
GetLoggerName() = name;
}

private:
/**
* @brief Returns the logger name (default: "Kappa").
* @return Logger name
*/
static std::string &GetLoggerName()
{
static std::string loggerName = "Kappa";
return loggerName;
}
static void SetLoggerName(const std::string &name);

public:
/**
Expand All @@ -54,11 +48,9 @@ namespace Kappa
* @param format Format string
* @param args Format arguments
*/
template<typename... Args>
void Trace(const std::source_location &loc, const std::string &format, Args &&...args)
template<typename... Args> void Trace(const std::source_location &loc, std::string_view format, Args &&...args)
{
logger_->trace(
"[{}:{}] {}", GetFileName(loc), loc.line(), std::vformat(format, std::make_format_args(args...)));
LogInternal(LogLevel::Trace, loc, format, std::make_format_args(args...));
}

/**
Expand All @@ -68,11 +60,9 @@ namespace Kappa
* @param format Format string
* @param args Format arguments
*/
template<typename... Args>
void Debug(const std::source_location &loc, const std::string &format, Args &&...args)
template<typename... Args> void Debug(const std::source_location &loc, std::string_view format, Args &&...args)
{
logger_->debug(
"[{}:{}] {}", GetFileName(loc), loc.line(), std::vformat(format, std::make_format_args(args...)));
LogInternal(LogLevel::Debug, loc, format, std::make_format_args(args...));
}

/**
Expand All @@ -82,10 +72,9 @@ namespace Kappa
* @param format Format string
* @param args Format arguments
*/
template<typename... Args> void Info(const std::source_location &loc, const std::string &format, Args &&...args)
template<typename... Args> void Info(const std::source_location &loc, std::string_view format, Args &&...args)
{
logger_->info(
"[{}:{}] {}", GetFileName(loc), loc.line(), std::vformat(format, std::make_format_args(args...)));
LogInternal(LogLevel::Info, loc, format, std::make_format_args(args...));
}

/**
Expand All @@ -95,10 +84,9 @@ namespace Kappa
* @param format Format string
* @param args Format arguments
*/
template<typename... Args> void Warn(const std::source_location &loc, const std::string &format, Args &&...args)
template<typename... Args> void Warn(const std::source_location &loc, std::string_view format, Args &&...args)
{
logger_->warn(
"[{}:{}] {}", GetFileName(loc), loc.line(), std::vformat(format, std::make_format_args(args...)));
LogInternal(LogLevel::Warn, loc, format, std::make_format_args(args...));
}

/**
Expand All @@ -108,11 +96,9 @@ namespace Kappa
* @param format Format string
* @param args Format arguments
*/
template<typename... Args>
void Error(const std::source_location &loc, const std::string &format, Args &&...args)
template<typename... Args> void Error(const std::source_location &loc, std::string_view format, Args &&...args)
{
logger_->error(
"[{}:{}] {}", GetFileName(loc), loc.line(), std::vformat(format, std::make_format_args(args...)));
LogInternal(LogLevel::Error, loc, format, std::make_format_args(args...));
}

/**
Expand All @@ -123,74 +109,37 @@ namespace Kappa
* @param args Format arguments
*/
template<typename... Args>
void Critical(const std::source_location &loc, const std::string &format, Args &&...args)
void Critical(const std::source_location &loc, std::string_view format, Args &&...args)
{
logger_->critical(
"[{}:{}] {}", GetFileName(loc), loc.line(), std::vformat(format, std::make_format_args(args...)));
}

/**
* @brief Returns the spdlog instance.
* @return spdlog logger
*/
spdlog::logger &GetSpdlog()
{
return *logger_;
}
const spdlog::logger &GetSpdlog() const
{
return *logger_;
LogInternal(LogLevel::Critical, loc, format, std::make_format_args(args...));
}

/**
* @brief Flushes the logger.
*/
void Flush()
{
logger_->flush();
}
void Flush();

/**
* @brief Sets the log level.
* @param level Log level
*/
void SetLevel(spdlog::level::level_enum level)
{
logger_->set_level(level);
}
void SetLevel(LogLevel level);

private:
/**
* @brief Constructs logger.
* @param spdlogger spdlog logger instance
*/
explicit Logger(std::shared_ptr<spdlog::logger> spdlogger) : logger_(std::move(spdlogger))
{
}
Logger();
~Logger();

/**
* @brief Extracts filename from full path.
* @param loc Source location
* @return Filename without path
*/
static std::string_view GetFileName(const std::source_location &loc)
{
const char *path = loc.file_name();
const char *filename = path;

for (const char *p = path; *p; ++p)
{
if (*p == '/' || *p == '\\')
{
filename = p + 1;
}
}
return filename;
}
void LogInternal(LogLevel level,
const std::source_location &loc,
std::string_view format,
std::format_args args);

std::shared_ptr<spdlog::logger> logger_;
};
static std::string &GetLoggerName();
static std::string_view GetFileName(const std::source_location &loc);

struct Impl;
std::unique_ptr<Impl> impl_;
};
} // namespace Kappa

/**
Expand Down
Loading
Loading