LogIt++
Header-only, macro-first C++ logging library
Loading...
Searching...
No Matches
EventLogLogger.hpp
Go to the documentation of this file.
1#pragma once
2#ifndef LOGIT_CPP_HEADER_LOGIT_CPP_LOGIT_LOGGERS_EVENTLOGLOGGER_HPP_INCLUDED
3#define LOGIT_CPP_HEADER_LOGIT_CPP_LOGIT_LOGGERS_EVENTLOGLOGGER_HPP_INCLUDED
4
5#include "ILogger.hpp"
6#include <atomic>
7#include <string>
8#include <memory>
9#include <mutex>
10
13
14#if defined(_WIN32) && defined(LOGIT_HAS_WIN_EVENT_LOG)
15#include <windows.h>
16#define LOGIT_WIN_EVENT_ENABLED 1
17#else
18#define LOGIT_WIN_EVENT_ENABLED 0
19#endif
20
21namespace logit {
22
23# if LOGIT_WIN_EVENT_ENABLED
24
28 class EventLogLogger : public ILogger {
29 public:
31 struct Config {
32 const wchar_t* source;
33 bool async;
34 bool use_dedicated_executor = false;
35 std::size_t queue_capacity = 0;
36 QueuePolicy queue_policy = QueuePolicy::Block;
40 Config(const wchar_t* s = L"LogIt", bool a = true) : source(s), async(a) {}
41 };
42
44 EventLogLogger() : EventLogLogger(Config()) {}
45
48 explicit EventLogLogger(const Config& c) : m_cfg(c) {
49 m_hsrc = RegisterEventSourceW(nullptr, m_cfg.source);
50 if (m_cfg.async && m_cfg.use_dedicated_executor) {
51 m_executor.reset(new detail::SingleThreadExecutor());
52 m_executor->set_max_queue_size(m_cfg.queue_capacity);
53 m_executor->set_queue_policy(m_cfg.queue_policy);
54 }
55 }
56
60 EventLogLogger(const wchar_t* source, bool async)
61 : EventLogLogger(Config(source, async)) {}
62
65 const wchar_t* source,
66 bool async,
67 bool use_dedicated_executor,
68 std::size_t queue_capacity,
69 QueuePolicy queue_policy)
70 : EventLogLogger(make_config(
71 source,
72 async,
73 use_dedicated_executor,
74 queue_capacity,
75 queue_policy)) {}
76
78 ~EventLogLogger() override { shutdown(); if (m_hsrc) DeregisterEventSource(m_hsrc); }
79
83 void log(const LogRecord& rec, const std::string& msg) override {
84 std::lock_guard<std::mutex> lifecycle_lock(m_lifecycle_mutex);
85 if (m_shutdown.load(std::memory_order_acquire)) return;
86 LogLevel lvl = rec.raw_mode ? LogLevel::LOG_LVL_INFO : rec.log_level;
87 bool raw_mode = rec.raw_mode;
88 std::string s = msg;
89 auto task = [this, lvl, raw_mode, s]() {
90 if (!raw_mode && static_cast<int>(lvl) < m_level.load()) return;
91 if (!m_hsrc) return;
92 WORD type = m_map(lvl);
93 int n = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), static_cast<int>(s.size()), nullptr, 0);
94 std::wstring wmsg; wmsg.resize(n);
95 MultiByteToWideChar(CP_UTF8, 0, s.c_str(), static_cast<int>(s.size()), &wmsg[0], n);
96 LPCWSTR arr[1] = { wmsg.c_str() };
97 ReportEventW(m_hsrc, type, 0, 0, nullptr, 1, 0, arr, nullptr);
98 };
99 if (m_cfg.async) { if (m_executor) { m_executor->add_task(task); } else { detail::TaskExecutor::get_instance().add_task(task); } }
100 else { task(); }
101 m_last_ts.store(rec.timestamp_ms);
102 }
103
107 std::string get_string_param(const LoggerParam& param) const override { return {}; }
108
112 int64_t get_int_param(const LoggerParam& param) const override { return 0; }
113
117 double get_float_param(const LoggerParam& param) const override { return 0.0; }
118
121 void set_log_level(LogLevel l) override { m_level.store(static_cast<int>(l)); }
122
125 LogLevel get_log_level() const override { return static_cast<LogLevel>(m_level.load()); }
126
128 void wait() override { if (m_cfg.async) { if (m_executor) { m_executor->wait(); } else { detail::TaskExecutor::get_instance().wait(); } } }
129
131 void shutdown() override {
132 {
133 std::lock_guard<std::mutex> lifecycle_lock(m_lifecycle_mutex);
134 if (m_shutdown.exchange(true, std::memory_order_acq_rel)) return;
135 }
136 if (m_executor) {
137 m_executor->shutdown();
138 } else if (m_cfg.async) {
140 }
141 }
142
143 private:
144 static WORD m_map(LogLevel l) {
145 switch (l) {
148 case LogLevel::LOG_LVL_INFO: return EVENTLOG_INFORMATION_TYPE;
149 case LogLevel::LOG_LVL_WARN: return EVENTLOG_WARNING_TYPE;
150 case LogLevel::LOG_LVL_ERROR: return EVENTLOG_ERROR_TYPE;
151 case LogLevel::LOG_LVL_FATAL: return EVENTLOG_ERROR_TYPE;
152 } return EVENTLOG_INFORMATION_TYPE;
153 }
154 Config m_cfg{};
155 std::mutex m_lifecycle_mutex;
156 HANDLE m_hsrc = nullptr;
157 std::atomic<int> m_level{static_cast<int>(LogLevel::LOG_LVL_TRACE)};
158 std::atomic<int64_t> m_last_ts{0};
159 std::atomic<bool> m_shutdown{false};
160 std::unique_ptr<detail::SingleThreadExecutor> m_executor;
161
162 static Config make_config(
163 const wchar_t* source,
164 bool async,
165 bool use_dedicated_executor,
166 std::size_t queue_capacity,
167 QueuePolicy queue_policy) {
168 Config config(source, async);
169 config.use_dedicated_executor = use_dedicated_executor;
170 config.queue_capacity = queue_capacity;
171 config.queue_policy = queue_policy;
172 return config;
173 }
174 };
175
176# else // stub
179 class EventLogLogger : public ILogger {
180 public:
182 struct Config {
183 const wchar_t* source;
184 bool async;
185 bool use_dedicated_executor = false;
186 std::size_t queue_capacity = 0;
187 QueuePolicy queue_policy = QueuePolicy::Block;
188 Config(const wchar_t* s = L"", bool a = false) : source(s), async(a) {}
189 };
190
193
196 explicit EventLogLogger(const Config& c) { (void)c; }
197
201 EventLogLogger(const wchar_t* source, bool async) { (void)source; (void)async; }
202
204 EventLogLogger(const wchar_t* source, bool async, bool use_dedicated_executor,
205 std::size_t queue_capacity, QueuePolicy queue_policy) {
206 (void)source; (void)async; (void)use_dedicated_executor;
207 (void)queue_capacity; (void)queue_policy;
208 }
209
213 void log(const LogRecord& rec, const std::string& msg) override { (void)rec; (void)msg; }
214
218 std::string get_string_param(const LoggerParam& param) const override { (void)param; return {}; }
219
223 int64_t get_int_param(const LoggerParam& param) const override { (void)param; return 0; }
224
228 double get_float_param(const LoggerParam& param) const override { (void)param; return 0.0; }
229
232 void set_log_level(LogLevel l) override { (void)l; }
233
236 LogLevel get_log_level() const override { return LogLevel::LOG_LVL_TRACE; }
237
239 void wait() override {}
240 };
241# endif
242
243} // namespace logit
244
245#endif // LOGIT_CPP_HEADER_LOGIT_CPP_LOGIT_LOGGERS_EVENTLOGLOGGER_HPP_INCLUDED
Defines the interface for loggers used in the logging system.
double get_float_param(const LoggerParam &param) const override
Return zero float parameter.
EventLogLogger()
Construct stub logger.
void log(const LogRecord &rec, const std::string &msg) override
Ignore log request.
void wait() override
No-op wait.
std::string get_string_param(const LoggerParam &param) const override
Return empty string parameter.
EventLogLogger(const wchar_t *source, bool async, bool use_dedicated_executor, std::size_t queue_capacity, QueuePolicy queue_policy)
Construct with parameters and ignored dedicated executor options.
LogLevel get_log_level() const override
Return default log level.
EventLogLogger(const wchar_t *source, bool async)
Construct with parameters.
void set_log_level(LogLevel l) override
Ignore level change.
EventLogLogger(const Config &c)
Construct with configuration.
int64_t get_int_param(const LoggerParam &param) const override
Return zero integer parameter.
virtual void shutdown()
Stops logger-owned asynchronous resources after draining pending work.
Definition ILogger.hpp:159
void add_task(std::function< void()> task)
Enqueue a task for asynchronous execution.
void wait()
Block until the queue is empty or a shutdown is requested.
static TaskExecutor & get_instance()
Returns the global executor instance.
QueuePolicy
Queue overflow handling policy used by TaskExecutor and SingleThreadExecutor.
The primary namespace for the LogIt++ library.
LogLevel
Logging levels.
Definition enums.hpp:15
@ LOG_LVL_TRACE
Trace level logging.
@ LOG_LVL_ERROR
Error level logging.
@ LOG_LVL_INFO
Information level logging.
@ LOG_LVL_FATAL
Fatal level logging.
@ LOG_LVL_DEBUG
Debug level logging.
@ LOG_LVL_WARN
Warning level logging.
LoggerParam
Enumeration for different logger parameters that can be retrieved.
Definition enums.hpp:47
detail::QueuePolicy QueuePolicy
Public queue overflow handling policy.
Definition loggers.hpp:20
bool use_dedicated_executor
Unused flag.
Config(const wchar_t *s=L"", bool a=false)
const wchar_t * source
Unused source name.
Stores log metadata and content.
Definition LogRecord.hpp:17