10 memset(Buffer, 0, 50);
13 Length = sprintf(Buffer, u8
"[%02d:%02d:%02d]", AHour, AMinute, ASecond);
15 Length = sprintf(Buffer, u8
"%02d-%02d-%02d", AHour, AMinute, ASecond);
25 auto Now(localtime(&Time));
26 const auto Hour(Now->tm_hour), Min(Now->tm_min), Sec(Now->tm_sec);
27 return TimeString(Hour, Min, Sec, AColons);
34 auto Now(localtime(&Time));
36 const int Year(Now->tm_year + 1900), Month(Now->tm_mon + 1), Day(Now->tm_mday), Hour(Now->tm_hour), Min(Now->tm_min), Sec(Now->tm_sec);
39 memset(Buffer, 0, 50);
40 const auto Length(sprintf(Buffer, u8
"Engine Log %d-%d-%d %s.txt", Year, Month, Day, TimeString(Hour, Min, Sec,
false).CString()));
48 auto LogPath(ABaseLogPath);
49 LogPath.Append(std::move(Formatted),
false,
false);
58 return OpenFileImpl(ABaseLogPath);
63 return OpenFileImpl(ThePath);
67 FHeap(
Parameters::LOGGER_HEAP_INITIAL_COMMIT_SIZE),
68 FContext(FHeap, AEmergencyLogger, true),
94 FContext.MakeCurrent();
96 CancelThreadedOperation();
103 auto& Message(AEntry->FMessage);
104 const auto ByteIndex(Message.IndexOfByte(
':', 3) + 1);
108 if (AEntry->FNext !=
nullptr)
109 LogShutdownForEntry(std::move(AEntry->FNext), AEmergency);
116 Queue = std::move(FQueueHead);
117 FQueueTail =
nullptr;
123 for (; Queue.get() !=
nullptr; Queue = std::move(NextNode)) {
124 NextNode = std::move(Queue->FNext);
125 const auto Len(static_cast<unsigned int>(Queue->FMessage.RawLength()));
128 const auto CurrentWrite(FFile.Write(Queue->FMessage.CString() + Written, Len - Written));
129 if (CurrentWrite == 0) {
133 EmergencyLogger.SetDebugLogging(
true);
134 EmergencyLogger.Log(
API::String::Static(u8
"Failed to write to primary log. Message follows:"), Level::ERR);
135 EmergencyLogger.Log(Queue->FMessage, Queue->FLevel);
136 if (NextNode !=
nullptr) {
138 LogShutdownForEntry(std::move(NextNode), EmergencyLogger);
142 Written += CurrentWrite;
143 }
while (Written < Len);
144 API::Assert::Equal<unsigned long long>(Written, Len);
154 while (!FCancelled.load(std::memory_order_relaxed)) {
155 if(!FPaused.load(std::memory_order_acquire))
162 FCancelled.store(
true, std::memory_order_relaxed);
166 const char* LevelString;
169 LevelString = u8
"Debug: ";
172 LevelString = u8
"Info: ";
175 LevelString = u8
"Warning: ";
178 LevelString = u8
"ERROR: ";
188 for (
auto I(1ULL); I < ThreadID; ++I)
198 if (ALevel != Level::DEV || FDevLog.load(std::memory_order_relaxed)) {
200 bool CritFail(
false);
205 Entry->FLevel = ALevel;
206 auto Tmp(Entry.get());
209 if (FQueueTail !=
nullptr)
210 FQueueTail->FNext = std::move(Entry);
212 FQueueHead = std::move(Entry);
236 if (FQueueHead ==
nullptr)
244 return FFile.GetPath()();
248 FDevLog.store(AEnable, std::memory_order_release);
253 FPaused.store(
true, std::memory_order_relaxed);
257 FPaused.store(
false, std::memory_order_relaxed);
A variable length UTF-8 string.
void Flush(void) const noexceptfinaloverride
Delays execution until all pending logs from the current thread have been written to the output...
A RAII locking mechanism.
The number of times to try and log again after a failed allocation before giving up.
#define DEBUG
Should be defined or not by user before all inclusions of CyberEngine.hpp. Enables engine debugging l...
void Pause(void) noexcept
Put the logging thread to sleep.
static API::String::Dynamic FormatLogMessage(const API::String::CStyle &AMessage, const Level ALevel)
Prepend the level and time to a log message.
The directory for storing data relevant only to this execution.
static API::String::Dynamic TimeString(const int AHour, const int AMinute, const int ASecond, const bool AColons)
Retrieve a string of the given time.
The File must not exist. It will be created.
static Platform::System::File OpenFile(void)
Prepares the logging File for writing. May block for one second if the preferred filename is taken in...
A string pointing to unchanging data in the stack above it or the data segment. Must have UTF-8 encod...
void CancelThreadedOperation(void) override
Stops the writer thread. Does not guarantee an empty queue.
Object< AObject > ConstructObject(AArgs &&...AArguments)
Allocates the Object specified by AObject using a specified Constructor.
Used for string of allocated variable length.
Context switching RAII helper.
static void LessThan(const AType &ALHS, const AType &ARHS) noexcept
Less than assertion function. May not be evaluated.
const API::String::CStyle & CurrentLog(void) const noexceptfinaloverride
Retrieve the string representation of the Path of the File the Logger is currently writing to...
Context FContext
The Context to be used when calling the Logger.
const unsigned int FErrorCode
The assigned error code.
Exceptions caused by external call failures or invalid external data. Only classifies ones that can p...
Compilation configuration variables.
API::Interop::Object< Platform::System::Thread > FThread
The thread used for writing to the log file.
A heap has no block large enough for a requested allocation and expansion failed. ...
void BeginThreadedOperation(void) override
Writer thread. Runs in a loop until CancelThreadedOperation is called.
Allocator & FAllocator
The Allocator.
API::UniquePointer< LogEntry > FQueueHead
The message queue head.
void Resume(void) noexcept
Wake the logging thread.
A basic char contained string.
void Log(const API::String::CStyle &AMessage, const Level ALevel) finaloverride
Log a message. Will be written to a text file on the Path returned by CurrentLog. ...
The basic multithreading interface.
Logger(API::Logger &AEmergencyLogger)
Initializes and starts the Logger. Changes the current Context. May block for one second if the prefe...
static Platform::System::File OpenFileImpl(const Platform::System::Path &ABasePath)
Prepares the logging File for writing. May block for one second if the preferred filename is taken in...
Precompiled header for inter-engine operations.
Level
The severity of the log.
A file that was to be created exists.
UniquePointer that uses our Allocator.
static void LogShutdownForEntry(API::UniquePointer< LogEntry > &&AEntry, API::Logger &AEmergency) noexcept
Takes a LogEntry Queue and logs it out to the current given emergency logger.
static Core & GetCore(void) noexcept
Retrieve the Core singleton.
~Logger()
Shutdown the Logger and empty the queue.
The interface for writing safe logs.
Exceptions indicating an API contract violation. Should not be anticipated.
API::Threadable & SelfAsThreadable(void) noexcept
Returns the current object as a Threadable reference. Used to get around some weird VS construction i...
Used for object which aren't allocatables.
void EmptyQueue(void)
Empty FQueue and write it into FFile.
Generic error for write failures. See functions for further documentation.
static Context & GetContext(void) noexcept
Get the API's Context.
void SetDebugLogging(const bool AEnable) noexceptfinaloverride
Enable/Disable filtering of Level::DEV logs.
An operation was attempted with an invalid enum code.
LogEntry * FQueueTail
The message queue tail.