MetaImGUI 1.0.0
ImGui Application Template for C++20
Loading...
Searching...
No Matches
Logger.h
Go to the documentation of this file.
1/*
2 MetaImGUI
3 Copyright (C) 2026 A P Nicholson
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
17*/
18
19#pragma once
20
21#include <atomic>
22#include <filesystem>
23#include <format>
24#include <memory>
25#include <string_view>
26
27// Heavy I/O and synchronisation headers (<fstream>, <sstream>, <mutex>) live
28// behind the pimpl in the .cpp so they don't leak into every TU that logs.
29// <filesystem> stays here because std::filesystem::path is part of the public API
30// and isn't reliably forward-declarable across libstdc++/libc++/MSVC STL.
31
32namespace MetaImGUI {
33
37enum class LogLevel {
38 Debug,
39 Info,
40 Warning,
41 Error,
42 Fatal
43};
44
57class Logger {
58public:
59 static Logger& Instance();
60
61 Logger(const Logger&) = delete;
62 Logger& operator=(const Logger&) = delete;
63 Logger(Logger&&) = delete;
64 Logger& operator=(Logger&&) = delete;
65
66 void Initialize(const std::filesystem::path& logFilePath, LogLevel minLevel = LogLevel::Info);
67 void Shutdown();
68
69 void SetLevel(LogLevel level) noexcept {
70 m_minLevel.store(level, std::memory_order_release);
71 }
72
73 [[nodiscard]] LogLevel GetLevel() const noexcept {
74 return m_minLevel.load(std::memory_order_acquire);
75 }
76
77 void SetConsoleOutput(bool enable);
78 void SetFileOutput(bool enable);
79 void Flush();
80
81 [[nodiscard]] std::filesystem::path GetLogFilePath() const;
82
83 template <typename... Args>
84 void Debug(std::format_string<Args...> fmt, Args... args) {
85 if (LogLevel::Debug >= GetLevel()) {
86 LogVFormat(LogLevel::Debug, fmt.get(), std::make_format_args(args...));
87 }
88 }
89
90 template <typename... Args>
91 void Info(std::format_string<Args...> fmt, Args... args) {
92 if (LogLevel::Info >= GetLevel()) {
93 LogVFormat(LogLevel::Info, fmt.get(), std::make_format_args(args...));
94 }
95 }
96
97 template <typename... Args>
98 void Warning(std::format_string<Args...> fmt, Args... args) {
99 if (LogLevel::Warning >= GetLevel()) {
100 LogVFormat(LogLevel::Warning, fmt.get(), std::make_format_args(args...));
101 }
102 }
103
104 template <typename... Args>
105 void Error(std::format_string<Args...> fmt, Args... args) {
106 if (LogLevel::Error >= GetLevel()) {
107 LogVFormat(LogLevel::Error, fmt.get(), std::make_format_args(args...));
108 }
109 }
110
111 template <typename... Args>
112 void Fatal(std::format_string<Args...> fmt, Args... args) {
113 if (LogLevel::Fatal >= GetLevel()) {
114 LogVFormat(LogLevel::Fatal, fmt.get(), std::make_format_args(args...));
115 }
116 }
117
118 // Overloads for plain string messages — skip vformat entirely.
119 void Debug(std::string_view message) {
120 if (LogLevel::Debug >= GetLevel()) {
121 LogPlain(LogLevel::Debug, message);
122 }
123 }
124 void Info(std::string_view message) {
125 if (LogLevel::Info >= GetLevel()) {
126 LogPlain(LogLevel::Info, message);
127 }
128 }
129 void Warning(std::string_view message) {
130 if (LogLevel::Warning >= GetLevel()) {
131 LogPlain(LogLevel::Warning, message);
132 }
133 }
134 void Error(std::string_view message) {
135 if (LogLevel::Error >= GetLevel()) {
136 LogPlain(LogLevel::Error, message);
137 }
138 }
139 void Fatal(std::string_view message) {
140 if (LogLevel::Fatal >= GetLevel()) {
141 LogPlain(LogLevel::Fatal, message);
142 }
143 }
144
145private:
146 Logger();
147 ~Logger();
148
149 // Pimpl holds <fstream>/<filesystem>/<mutex> so they don't leak into TUs.
150 // The destructor is defined in the .cpp so unique_ptr<Impl> can hold an
151 // incomplete type here.
152 struct Impl;
153 std::unique_ptr<Impl> m_impl;
154
155 // Hot-path: read by every Debug/Info/... template before any locking.
156 std::atomic<LogLevel> m_minLevel{LogLevel::Info};
157
158 void LogVFormat(LogLevel level, std::string_view fmt, std::format_args args);
159 void LogPlain(LogLevel level, std::string_view message);
160};
161
162} // namespace MetaImGUI
163
164// Convenience macros
165#define LOG_DEBUG(...) MetaImGUI::Logger::Instance().Debug(__VA_ARGS__)
166#define LOG_INFO(...) MetaImGUI::Logger::Instance().Info(__VA_ARGS__)
167#define LOG_WARNING(...) MetaImGUI::Logger::Instance().Warning(__VA_ARGS__)
168#define LOG_ERROR(...) MetaImGUI::Logger::Instance().Error(__VA_ARGS__)
169#define LOG_FATAL(...) MetaImGUI::Logger::Instance().Fatal(__VA_ARGS__)
Thread-safe logger with file and console output.
Definition Logger.h:57
void SetFileOutput(bool enable)
Definition Logger.cpp:151
Logger & operator=(const Logger &)=delete
void SetLevel(LogLevel level) noexcept
Definition Logger.h:69
void Debug(std::string_view message)
Definition Logger.h:119
void SetConsoleOutput(bool enable)
Definition Logger.cpp:146
void Warning(std::format_string< Args... > fmt, Args... args)
Definition Logger.h:98
Logger & operator=(Logger &&)=delete
void Initialize(const std::filesystem::path &logFilePath, LogLevel minLevel=LogLevel::Info)
Definition Logger.cpp:105
void Info(std::string_view message)
Definition Logger.h:124
void Warning(std::string_view message)
Definition Logger.h:129
void Debug(std::format_string< Args... > fmt, Args... args)
Definition Logger.h:84
Logger(Logger &&)=delete
Logger(const Logger &)=delete
void Error(std::string_view message)
Definition Logger.h:134
static Logger & Instance()
Definition Logger.cpp:100
void Fatal(std::format_string< Args... > fmt, Args... args)
Definition Logger.h:112
void Info(std::format_string< Args... > fmt, Args... args)
Definition Logger.h:91
LogLevel GetLevel() const noexcept
Definition Logger.h:73
void Fatal(std::string_view message)
Definition Logger.h:139
std::filesystem::path GetLogFilePath() const
Definition Logger.cpp:165
void Error(std::format_string< Args... > fmt, Args... args)
Definition Logger.h:105
LogLevel
Log severity levels.
Definition Logger.h:37
@ Warning
Warning messages.
@ Info
Informational messages.
@ Fatal
Fatal error messages.
@ Error
Error messages.
@ Debug
Detailed debugging information.
@ Info
Information icon.