/*** Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: EventLog.Win32.cpp Date: 2022-2-6 Author: Reece ***/ #include #include "EventLog.Win32.hpp" namespace Aurora::Logging::Sinks { static const auto kMagicEventNumber = 1000; EventLogSink::EventLogSink(const AuString &value) { this->winCurrentSink_ = RegisterEventSourceW(NULL, Locale::ConvertFromUTF8(value).c_str()); } EventLogSink::~EventLogSink() { DeregisterEventSource(winCurrentSink_); } bool EventLogSink::OnMessageNonblocking(AuUInt8 level, const ConsoleMessage &msg) { if (this->winCurrentSink_ == INVALID_HANDLE_VALUE) { return false; } return true; } void EventLogSink::OnMessageBlocking(AuUInt8 level, const ConsoleMessage &msg) { if (this->winCurrentSink_ == INVALID_HANDLE_VALUE) { return; } AU_LOCK_GUARD(this->spinLock_); WORD type {}; switch (level) { case (AuUInt8)ELogLevel::eInfo: type = EVENTLOG_SUCCESS; break; case (AuUInt8)ELogLevel::eError: type = EVENTLOG_ERROR_TYPE; break; case (AuUInt8)ELogLevel::eDebug: case (AuUInt8)ELogLevel::eVerbose: type = EVENTLOG_INFORMATION_TYPE; break; case (AuUInt8)ELogLevel::eWarn: type = EVENTLOG_WARNING_TYPE; break; default: type = EVENTLOG_INFORMATION_TYPE; } if (this->winCurrentType_ != type) { FlushStrings(); this->winCurrentType_ = type; } auto a = Locale::ConvertFromUTF8(msg.ToPersistentString()); if (this->winArrayBuffer_.size() + a.size() + 2 >= 32 * 1000) { FlushStrings(); } this->winArrayBuffer_.insert(this->winArrayBuffer_.end(), a.begin(), a.end()); this->winArrayBuffer_.insert(this->winArrayBuffer_.end(), L"\r\n", L"\r\n" + 2); } void EventLogSink::FlushStrings() { if (this->winArrayBuffer_.empty()) { return; } this->winCompleteArrayBuffer_.push_back(AuMakeTuple(this->winCurrentType_, AuMove(this->winArrayBuffer_))); this->winArrayBuffer_.clear(); this->winArrayBuffer_.reserve(15 * 1024); } void EventLogSink::OnFlush() { if (this->winCurrentSink_ == INVALID_HANDLE_VALUE) { return; } AU_LOCK_GUARD(this->spinLock_); FlushStrings(); for (auto &sortedMessages : this->winCompleteArrayBuffer_) { auto &strs = AuGet<1>(sortedMessages); auto handle = strs.data(); ReportEventW(this->winCurrentSink_, AuGet<0>(sortedMessages), 0, kMagicEventNumber, NULL, 1, 0, (CONST WCHAR **)&handle, NULL); } this->winCompleteArrayBuffer_.clear(); } IBasicSink *NewOSNamedEventDirectorySinkNew(const AuString &name) { try { return _new EventLogSink(name); } catch (...) { return {}; } } void NewOSNamedEventDirectorySinkRelease(IBasicSink *sink) { AuSafeDelete< EventLogSink *>(sink); } }