SP3-15 Added Logging & Exception Handling Tools #6
|
@ -60,7 +60,7 @@
|
|||
<PrecompiledHeaderFile>SBpch.h</PrecompiledHeaderFile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>.;..\SHADE_Engine\src;src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\Dependencies\spdlog\include;..\SHADE_Engine\src;src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
|
@ -80,7 +80,7 @@
|
|||
<PrecompiledHeaderFile>SBpch.h</PrecompiledHeaderFile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PreprocessorDefinitions>_RELEASE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>.;..\SHADE_Engine\src;src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\Dependencies\spdlog\include;..\SHADE_Engine\src;src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<Optimization>Full</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Application">
|
||||
<UniqueIdentifier>{D9DE78AF-4594-F1A4-CE88-EB7B3A3DE8A8}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Scenes">
|
||||
<UniqueIdentifier>{86EEB3D0-7290-DEA6-5B4B-F2FA478C65F7}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\Application\SBApplication.h">
|
||||
<Filter>Application</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\SBpch.h" />
|
||||
<ClInclude Include="src\Scenes\SBTestScene.h">
|
||||
<Filter>Scenes</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\Application\SBApplication.cpp">
|
||||
<Filter>Application</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\SBpch.cpp" />
|
||||
<ClCompile Include="src\Scenes\SBTestScene.cpp">
|
||||
<Filter>Scenes</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\WinMain.cpp" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -21,8 +21,7 @@ project "SHADE_Application"
|
|||
|
||||
includedirs
|
||||
{
|
||||
"%{IncludeDir.GLFW}",
|
||||
"%{IncludeDir.GLAD}",
|
||||
"%{IncludeDir.spdlog}/include",
|
||||
"../SHADE_Engine/src",
|
||||
"src"
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@ namespace Sandbox
|
|||
bool paused = false;
|
||||
void SBApplication::Initialize(void)
|
||||
{
|
||||
|
||||
|
||||
#ifdef SHEDITOR
|
||||
#else
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "SBpch.h"
|
||||
#include <Engine/SHEngine.h>
|
||||
#include <Tools/SHLogger.h>
|
||||
#include <Tools/SHExceptionHandler.h>
|
||||
#include "Application/SBApplication.h"
|
||||
|
||||
|
||||
|
@ -15,15 +17,35 @@
|
|||
#define DBG_NEW new
|
||||
#endif
|
||||
|
||||
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
||||
PSTR lpCmdLine, INT nCmdShow)
|
||||
INT WINAPI WinMain
|
||||
(
|
||||
_In_ HINSTANCE /*hInstance*/,
|
||||
_In_opt_ HINSTANCE /*hPrevInstance*/,
|
||||
_In_ PSTR /*lpCmdLine*/,
|
||||
_In_ INT /*nCmdShow*/
|
||||
)
|
||||
{
|
||||
const SHADE::SHLogger::Config LOGGER_CONFIG{ .directoryPath = "./logs/" };
|
||||
SHADE::SHLogger::Initialise(LOGGER_CONFIG);
|
||||
|
||||
try
|
||||
{
|
||||
#ifndef SHEDITOR
|
||||
ShowWindow(::GetConsoleWindow(), SW_HIDE);
|
||||
//ShowWindow(::GetConsoleWindow(), SW_HIDE);
|
||||
#endif
|
||||
|
||||
SHLOG_INFO("sup")
|
||||
|
||||
SHADE::SHEngine::Run<Sandbox::SBApplication>();
|
||||
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
SHADE::SHExceptionHandler::HandleException(std::current_exception());
|
||||
SHADE::SHLogger::Shutdown();
|
||||
}
|
||||
|
||||
SHADE::SHLogger::Shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -117,9 +117,12 @@
|
|||
<ClInclude Include="src\Engine\ECS_Base\System\SHSystemManager.h" />
|
||||
<ClInclude Include="src\Engine\SHEngine.h" />
|
||||
<ClInclude Include="src\Meta\SHIsDetected.h" />
|
||||
<ClInclude Include="src\SHpch.h" />
|
||||
<ClInclude Include="src\Scene\SHScene.h" />
|
||||
<ClInclude Include="src\Scene\SHSceneManager.h" />
|
||||
<ClInclude Include="src\SHpch.h" />
|
||||
<ClInclude Include="src\Tools\SHException.h" />
|
||||
<ClInclude Include="src\Tools\SHExceptionHandler.h" />
|
||||
<ClInclude Include="src\Tools\SHLogger.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\Engine\ECS_Base\Components\SHComponent.cpp" />
|
||||
|
@ -129,10 +132,13 @@
|
|||
<ClCompile Include="src\Engine\ECS_Base\System\SHEntityManager.cpp" />
|
||||
<ClCompile Include="src\Engine\ECS_Base\System\SHSystemManager.cpp" />
|
||||
<ClCompile Include="src\Engine\SHEngine.cpp" />
|
||||
<ClCompile Include="src\Scene\SHSceneManager.cpp" />
|
||||
<ClCompile Include="src\SHpch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Scene\SHSceneManager.cpp" />
|
||||
<ClCompile Include="src\Tools\SHException.cpp" />
|
||||
<ClCompile Include="src\Tools\SHExceptionHandler.cpp" />
|
||||
<ClCompile Include="src\Tools\SHLogger.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Dependencies\yamlcpp\yaml-cpp.vcxproj">
|
||||
|
|
|
@ -19,6 +19,15 @@
|
|||
<Filter Include="Engine\ECS_Base\System">
|
||||
<UniqueIdentifier>{B3E3FAFD-9FDD-2350-884A-BA6074E389BC}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Meta">
|
||||
<UniqueIdentifier>{AC05897C-983C-8A0D-4129-70102D3F060F}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Scene">
|
||||
<UniqueIdentifier>{B3F7140E-1F0C-3DBF-E88D-E01E546139F0}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Tools">
|
||||
<UniqueIdentifier>{16CF2D0E-82E3-55BF-4B65-F91EB73852F0}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\Engine\ECS_Base\Components\SHComponent.h">
|
||||
|
@ -63,10 +72,25 @@
|
|||
<ClInclude Include="src\Engine\SHEngine.h">
|
||||
<Filter>Engine</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\Meta\SHIsDetected.h">
|
||||
<Filter>Meta</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\SHpch.h" />
|
||||
<ClInclude Include="src\Meta\SHIsDetected.h" />
|
||||
<ClInclude Include="src\Scene\SHScene.h" />
|
||||
<ClInclude Include="src\Scene\SHSceneManager.h" />
|
||||
<ClInclude Include="src\Scene\SHScene.h">
|
||||
<Filter>Scene</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\Scene\SHSceneManager.h">
|
||||
<Filter>Scene</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\Tools\SHException.h">
|
||||
<Filter>Tools</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\Tools\SHExceptionHandler.h">
|
||||
<Filter>Tools</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\Tools\SHLogger.h">
|
||||
<Filter>Tools</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\Engine\ECS_Base\Components\SHComponent.cpp">
|
||||
|
@ -91,6 +115,17 @@
|
|||
<Filter>Engine</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\SHpch.cpp" />
|
||||
<ClCompile Include="src\Scene\SHSceneManager.cpp" />
|
||||
<ClCompile Include="src\Scene\SHSceneManager.cpp">
|
||||
<Filter>Scene</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Tools\SHException.cpp">
|
||||
<Filter>Tools</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Tools\SHExceptionHandler.cpp">
|
||||
<Filter>Tools</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Tools\SHLogger.cpp">
|
||||
<Filter>Tools</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -1 +1,10 @@
|
|||
/****************************************************************************************
|
||||
* \file SHpch.h
|
||||
* \brief Empty source file for generating SHADE Engine's precompiled header.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#include "SHpch.h"
|
|
@ -0,0 +1,12 @@
|
|||
/****************************************************************************************
|
||||
* \file SHpch.h
|
||||
* \brief Precompiled header file for SHADE Engine.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
|
@ -0,0 +1,51 @@
|
|||
/****************************************************************************************
|
||||
* \file SHException.cpp
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Implementation for custom exception types of SHADE Engine.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#include <SHpch.h>
|
||||
|
||||
// Primary Header
|
||||
#include "SHException.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHException::SHException(std::string msg, const std::source_location& src) noexcept
|
||||
: message { std::move(msg) }
|
||||
, origin { src }
|
||||
{}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Public Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
const char* SHException::what() const noexcept
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "SHException " << GetOriginString();
|
||||
message = ss.str();
|
||||
|
||||
return message.c_str();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Private Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
std::string SHException::GetOriginString() const noexcept
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "[" << origin.file_name() << ", " << origin.line() << "]";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
|
@ -0,0 +1,84 @@
|
|||
/****************************************************************************************
|
||||
* \file SHException.h
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Interface for custom exception types of SHADE Engine.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <source_location>
|
||||
#include <string_view>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
|
||||
// Project Headers
|
||||
#include "SHLogger.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Concepts */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
template <typename ExceptionType>
|
||||
concept IsException = std::is_base_of_v<std::exception, ExceptionType>;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Base exception type thrown by SHADE Engine.
|
||||
*/
|
||||
class SHException : public std::exception
|
||||
{
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHException
|
||||
(
|
||||
std::string msg = "",
|
||||
const std::source_location& src = std::source_location::current()
|
||||
) noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
const char* what() const noexcept override;
|
||||
|
||||
protected:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
mutable std::string message;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
std::string GetOriginString() const noexcept;
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
const std::source_location& origin;
|
||||
};
|
||||
}
|
||||
|
||||
#define SHASSERT(cond, msg) \
|
||||
if (!(cond)) \
|
||||
{ \
|
||||
SHLOGV_CRITICAL(msg) \
|
||||
std::abort(); \
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/****************************************************************************************
|
||||
* \file SHExceptionHandler.cpp
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Implementation for SHADE Engine's exception handler.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#include <SHpch.h>
|
||||
|
||||
// Primary Header
|
||||
#include "SHExceptionHandler.h"
|
||||
|
||||
// Project Headers
|
||||
#include "SHException.h"
|
||||
#include "SHLogger.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Static Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
bool SHExceptionHandler::HandleException(const std::exception_ptr& exceptionPtr)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Re-throw all valid exception types
|
||||
if (exceptionPtr)
|
||||
{
|
||||
std::rethrow_exception(exceptionPtr);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
SHLOG_CRITICAL(e.what())
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// Catch any non-std::exception derived types and consider them as unknown.
|
||||
SHLOG_CRITICAL("SHADE Engine has experienced an unknown fatal error!")
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
|
@ -0,0 +1,37 @@
|
|||
/****************************************************************************************
|
||||
* \file SHExceptionHandler.h
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Interface for SHADE Engine's exception handler.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <exception>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
class SHExceptionHandler
|
||||
{
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Static Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Catches and logs any exceptions thrown. If the exception's type is
|
||||
* SHAssertException, the application will not end unless crashOnAssert is set
|
||||
* to true.
|
||||
* @param exceptionPtr Pointer to the exception that was caught.
|
||||
* @returns True if the application should continue running after an exception was caught.
|
||||
*/
|
||||
static bool HandleException(const std::exception_ptr& exceptionPtr);
|
||||
};
|
||||
} // namespace SHADE
|
|
@ -0,0 +1,441 @@
|
|||
/****************************************************************************************
|
||||
* \file SHLogger.cpp
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Implementation for SHADE Engine's logger.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#include <SHpch.h>
|
||||
|
||||
// Primary Header
|
||||
#include "SHLogger.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <chrono>
|
||||
|
||||
#include <spdlog/sinks/stdout_color_sinks.h>
|
||||
#include <spdlog/sinks/basic_file_sink.h>
|
||||
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
/* Local Helper Function Declarations */
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
std::string GetDatePattern (SHADE::SHLogger::DateFormat fmt);
|
||||
std::string GetClockPattern (bool is24HR);
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Static Data Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
unsigned char SHLogger::configFlags = DEFAULT_CONFIG_FLAG;
|
||||
SHLogger::DateFormat SHLogger::dateFormat = SHLogger::DateFormat::DD_MM_YY;
|
||||
std::string SHLogger::trivialPattern;
|
||||
std::string SHLogger::verbosePattern;
|
||||
|
||||
std::string SHLogger::fileName;
|
||||
std::filesystem::path SHLogger::directoryPath;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Setter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHLogger::SetConfig(const Config& config) noexcept
|
||||
{
|
||||
unsigned char flags = 0U;
|
||||
|
||||
if (config.showTime)
|
||||
flags |= 1U << 0;
|
||||
|
||||
if (config.clockFormat == ClockFormat::_24HR)
|
||||
flags |= 1U << 1;
|
||||
|
||||
if (config.showDate)
|
||||
flags |= 1U << 2;
|
||||
|
||||
if (config.showFunctionFileName)
|
||||
flags |= 1U << 3;
|
||||
|
||||
if (config.showFunctionLineNumber)
|
||||
flags |= 1U << 4;
|
||||
|
||||
configFlags = flags;
|
||||
dateFormat = config.dateFormat;
|
||||
|
||||
fileName = config.fileName;
|
||||
directoryPath = config.directoryPath;
|
||||
|
||||
UpdatePatterns();
|
||||
}
|
||||
|
||||
void SHLogger::SetShowTime(bool showTime) noexcept
|
||||
{
|
||||
constexpr char RAW = 1U << 0;
|
||||
showTime ? configFlags |= RAW : configFlags &= ~(RAW);
|
||||
UpdatePatterns();
|
||||
}
|
||||
|
||||
void SHLogger::SetShowDate(bool showDate) noexcept
|
||||
{
|
||||
constexpr char RAW = 1U << 2;
|
||||
showDate ? configFlags |= RAW : configFlags &= ~(RAW);
|
||||
UpdatePatterns();
|
||||
}
|
||||
|
||||
void SHLogger::SetShowFunctionFileName(bool showFunctionFileName) noexcept
|
||||
{
|
||||
constexpr char RAW = 1U << 3;
|
||||
showFunctionFileName ? configFlags |= RAW : configFlags &= ~(RAW);
|
||||
UpdatePatterns();
|
||||
}
|
||||
|
||||
void SHLogger::SetShowFunctionLineNumber(bool showFunctionLineNumber) noexcept
|
||||
{
|
||||
constexpr char RAW = 1U << 4;
|
||||
showFunctionLineNumber ? configFlags |= RAW : configFlags &= ~(RAW);
|
||||
UpdatePatterns();
|
||||
}
|
||||
|
||||
void SHLogger::SetClockFormat(ClockFormat newClockFormat) noexcept
|
||||
{
|
||||
constexpr char RAW = 1U << 1;
|
||||
newClockFormat == ClockFormat::_24HR ? configFlags |= RAW : configFlags &= ~(RAW);
|
||||
UpdatePatterns();
|
||||
}
|
||||
|
||||
void SHLogger::SetDateFormat(DateFormat newDateFormat) noexcept
|
||||
{
|
||||
dateFormat = newDateFormat;
|
||||
UpdatePatterns();
|
||||
}
|
||||
|
||||
void SHLogger::SetFileName(const std::string& logFileName) noexcept
|
||||
{
|
||||
if (CheckInitialisation("Logger has already been initialised!"))
|
||||
return;
|
||||
|
||||
fileName = logFileName;
|
||||
}
|
||||
|
||||
void SHLogger::SetDirectoryPath(const std::filesystem::path& logDirectoryPath) noexcept
|
||||
{
|
||||
if (CheckInitialisation("Logger has already been initialised!"))
|
||||
return;
|
||||
|
||||
if (!is_directory(logDirectoryPath))
|
||||
{
|
||||
spdlog::get(SHLOGGER_NAME)->info("Supplied path is not a directory!");
|
||||
return;
|
||||
}
|
||||
|
||||
directoryPath = logDirectoryPath;
|
||||
}
|
||||
|
||||
void SHLogger::SetFlushTime(int seconds) noexcept
|
||||
{
|
||||
spdlog::flush_every(std::chrono::seconds(seconds));
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Public Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHLogger::Initialise(const Config& config)
|
||||
{
|
||||
SetConfig(config);
|
||||
|
||||
// Initialise default fileName if fileName was not set
|
||||
if (fileName.empty())
|
||||
{
|
||||
// Get current date and time
|
||||
const auto NOW = std::time(nullptr);
|
||||
std::tm localTime;
|
||||
localtime_s(&localTime, &NOW);
|
||||
|
||||
std::stringstream tmp;
|
||||
tmp << "SHADE Log_" << std::put_time(&localTime, "%F %H.%M.%S") << ".txt";
|
||||
|
||||
fileName = tmp.str();
|
||||
}
|
||||
|
||||
CreateConsole();
|
||||
|
||||
try
|
||||
{
|
||||
std::vector<spdlog::sink_ptr> sinks;
|
||||
|
||||
// Colour console
|
||||
const auto& COLOUR_CONSOLE_SINK = sinks.emplace_back(std::make_shared<spdlog::sinks::stdout_color_sink_mt>());
|
||||
COLOUR_CONSOLE_SINK->set_pattern("%^" + trivialPattern + "%v%$");
|
||||
|
||||
// File
|
||||
const std::string FULL_FILE_PATH = directoryPath.string() + fileName;
|
||||
const auto& FILE_SINK = sinks.emplace_back(std::make_shared<spdlog::sinks::basic_file_sink_mt>(FULL_FILE_PATH));
|
||||
FILE_SINK->set_pattern(trivialPattern + "%v");
|
||||
|
||||
// Create and register logger with spdlog
|
||||
const auto LOGGER = std::make_shared<spdlog::logger>(SHLOGGER_NAME, sinks.begin(), sinks.end());
|
||||
LOGGER->set_level(spdlog::level::trace);
|
||||
LOGGER->flush_on(spdlog::level::trace);
|
||||
register_logger(LOGGER);
|
||||
|
||||
// Flush every 3 seconds
|
||||
spdlog::flush_every(std::chrono::seconds(config.flushTime));
|
||||
|
||||
configFlags |= (1U << 7);
|
||||
}
|
||||
catch (const spdlog::spdlog_ex& e)
|
||||
{
|
||||
std::cout << "Log initialisation failed: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void SHLogger::Shutdown() noexcept
|
||||
{
|
||||
spdlog::shutdown();
|
||||
}
|
||||
|
||||
void SHLogger::UseTrivialPattern() noexcept
|
||||
{
|
||||
auto& sinks = spdlog::get(SHLOGGER_NAME)->sinks();
|
||||
sinks[0]->set_pattern("%^" + trivialPattern + "%v%$"); // Colour Console Sink
|
||||
sinks[1]->set_pattern(trivialPattern + "%v"); // File Sink
|
||||
}
|
||||
|
||||
void SHLogger::UseVerbosePattern() noexcept
|
||||
{
|
||||
auto& sinks = spdlog::get(SHLOGGER_NAME)->sinks();
|
||||
sinks[0]->set_pattern("%^" + verbosePattern + "%v%$"); // Colour Console Sink
|
||||
sinks[1]->set_pattern(verbosePattern + "%v"); // File Sink
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Private Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
bool SHLogger::CreateConsole()
|
||||
{
|
||||
bool result = false;
|
||||
DestroyConsole();
|
||||
|
||||
if (AllocConsole())
|
||||
{
|
||||
const HANDLE CONSOLE = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
// Set the screen buffer to be big enough to scroll some text
|
||||
CONSOLE_SCREEN_BUFFER_INFO conInfo;
|
||||
GetConsoleScreenBufferInfo(CONSOLE, &conInfo);
|
||||
|
||||
if (conInfo.dwSize.Y < DEFAULT_CONSOLE_LEN)
|
||||
{
|
||||
conInfo.dwSize.Y = DEFAULT_CONSOLE_LEN;
|
||||
}
|
||||
|
||||
SetConsoleScreenBufferSize(CONSOLE, conInfo.dwSize);
|
||||
|
||||
result = RedirectConsoleIO();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SHLogger::RedirectConsoleIO()
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
FILE* fp;
|
||||
|
||||
// Redirect STDIN if the console has an input handle
|
||||
if (GetStdHandle(STD_INPUT_HANDLE) != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (freopen_s(&fp, "CONIN$", "r", stdin) != 0)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
setvbuf(stdin, nullptr, _IONBF, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Redirect STDOUT if the console has an output handle
|
||||
if (GetStdHandle(STD_OUTPUT_HANDLE) != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (freopen_s(&fp, "CONOUT$", "w", stdout) != 0)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Redirect STDERR if the console has an error handle
|
||||
if (GetStdHandle(STD_ERROR_HANDLE) != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (freopen_s(&fp, "CONOUT$", "w", stderr) != 0)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
setvbuf(stderr, nullptr, _IONBF, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Make C++ standard streams point to console as well.
|
||||
std::ios::sync_with_stdio(true);
|
||||
|
||||
// Clear the error state for each of the C++ standard streams.
|
||||
std::wcin.clear();
|
||||
std::cin.clear();
|
||||
std::wcout.clear();
|
||||
std::cout.clear();
|
||||
std::wcerr.clear();
|
||||
std::cerr.clear();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool SHLogger::DestroyConsole()
|
||||
{
|
||||
bool result = true;
|
||||
FILE* fP;
|
||||
|
||||
// Just to be safe, redirect standard IO to NUL before releasing.
|
||||
|
||||
// Redirect STDIN to NUL
|
||||
if (freopen_s(&fP, "NUL:", "r", stdin) != 0)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
setvbuf(stdin, nullptr, _IONBF, 0);
|
||||
}
|
||||
|
||||
|
||||
// Redirect STDOUT to NUL
|
||||
if (freopen_s(&fP, "NUL:", "w", stdout) != 0)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
}
|
||||
|
||||
// Redirect STDERR to NUL
|
||||
if (freopen_s(&fP, "NUL:", "w", stderr) != 0)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
setvbuf(stderr, nullptr, _IONBF, 0);
|
||||
}
|
||||
|
||||
// Detach console
|
||||
if (result)
|
||||
return FreeConsole();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SHLogger::CheckInitialisation(const std::string_view& msg)
|
||||
{
|
||||
const bool INITIALISED = configFlags & (1U << 7);
|
||||
if (INITIALISED)
|
||||
{
|
||||
spdlog::get(SHLOGGER_NAME)->warn(msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void SHLogger::UpdatePatterns()
|
||||
{
|
||||
const std::string DATE_TIME_PATTERN = BuildDateTimePattern();
|
||||
const std::string VERBOSE_PATTERN = BuildVerbosePattern();
|
||||
|
||||
trivialPattern = DATE_TIME_PATTERN;
|
||||
verbosePattern = DATE_TIME_PATTERN + VERBOSE_PATTERN;
|
||||
}
|
||||
|
||||
std::string SHLogger::BuildDateTimePattern()
|
||||
{
|
||||
const bool SHOW_TIME = configFlags & (1U << 0);
|
||||
const bool SHOW_DATE = configFlags & (1U << 2);
|
||||
|
||||
std::string pattern;
|
||||
if (SHOW_DATE || SHOW_TIME)
|
||||
{
|
||||
pattern.append("[");
|
||||
{
|
||||
if (SHOW_DATE)
|
||||
{
|
||||
pattern.append(GetDatePattern(dateFormat));
|
||||
}
|
||||
|
||||
// Put a space in between date and time
|
||||
if (SHOW_DATE && SHOW_TIME)
|
||||
{
|
||||
pattern.append(" ");
|
||||
}
|
||||
|
||||
if (SHOW_TIME)
|
||||
{
|
||||
const bool IS_24HR = configFlags & (1U << 1);
|
||||
pattern.append(GetClockPattern(IS_24HR));
|
||||
}
|
||||
}
|
||||
pattern.append("] ");
|
||||
}
|
||||
|
||||
return pattern;
|
||||
}
|
||||
|
||||
std::string SHLogger::BuildVerbosePattern()
|
||||
{
|
||||
const bool SHOW_SRC_FILE = configFlags & (1U << 3);
|
||||
const bool SHOW_SRC_LINE = configFlags & (1U << 4);
|
||||
|
||||
std::string pattern { "[" };
|
||||
if (SHOW_SRC_FILE)
|
||||
{
|
||||
pattern.append("%s, ");
|
||||
if (SHOW_SRC_LINE)
|
||||
{
|
||||
pattern.append("%#, ");
|
||||
}
|
||||
}
|
||||
|
||||
pattern.append("%!] ");
|
||||
return pattern;
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
||||
|
||||
std::string GetDatePattern(SHADE::SHLogger::DateFormat fmt)
|
||||
{
|
||||
switch (fmt)
|
||||
{
|
||||
case SHADE::SHLogger::DateFormat::DD_MM_YY: return std::string { "%d-%m-%Y" };
|
||||
case SHADE::SHLogger::DateFormat::MM_DD_YY: return std::string { "%m-%d-%Y" };
|
||||
case SHADE::SHLogger::DateFormat::YY_MM_DD: return std::string { "%Y-%m-%d" };
|
||||
case SHADE::SHLogger::DateFormat::DD_Mth_YY: return std::string { "%d %b, %Y" };
|
||||
case SHADE::SHLogger::DateFormat::Mth_DD_YY: return std::string { "%b %d, %Y" };
|
||||
|
||||
default: return std::string { "%d-%m-%Y" };
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetClockPattern(bool is24HR)
|
||||
{
|
||||
return is24HR ? "%H:%M:%S" : "%I:%M:%S %p";
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
/****************************************************************************************
|
||||
* \file SHLogger.h
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Interface for SHADE Engine's logger.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
#include <filesystem>
|
||||
|
||||
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_TRACE
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
/* Macros */
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
#define SHLOGGER_NAME "SHLogger"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
class SHLogger
|
||||
{
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
enum class ClockFormat { _12HR, _24HR };
|
||||
|
||||
enum class DateFormat
|
||||
{
|
||||
DD_MM_YY // 25-12-2022
|
||||
, MM_DD_YY // 12-25-2022
|
||||
, YY_MM_DD // 2022-12-25
|
||||
, DD_Mth_YY // 25 Dec, 2022
|
||||
, Mth_DD_YY // Dec 25, 2022
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Defines configuration parameters for the logger.
|
||||
*/
|
||||
struct Config
|
||||
{
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
bool showTime = true;
|
||||
bool showDate = true;
|
||||
bool showFunctionFileName = true;
|
||||
bool showFunctionLineNumber = true;
|
||||
|
||||
ClockFormat clockFormat = ClockFormat::_12HR;
|
||||
DateFormat dateFormat = DateFormat::DD_MM_YY;
|
||||
std::string fileName;
|
||||
std::filesystem::path directoryPath;
|
||||
|
||||
int flushTime = 1;
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
[[nodiscard]] static const std::string& GetTrivialPattern () noexcept { return trivialPattern; }
|
||||
[[nodiscard]] static const std::string& GetVerbosePattern () noexcept { return verbosePattern; }
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Setter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
static void SetTrivialPattern (const std::string& pattern) noexcept { trivialPattern = pattern; }
|
||||
static void SetVerbosePattern (const std::string& pattern) noexcept { verbosePattern = pattern; }
|
||||
|
||||
static void SetConfig (const Config& config) noexcept;
|
||||
|
||||
static void SetShowTime (bool showTime) noexcept;
|
||||
static void SetShowDate (bool showDate) noexcept;
|
||||
static void SetShowFunctionFileName (bool showFunctionFileName) noexcept;
|
||||
static void SetShowFunctionLineNumber (bool showFunctionLineNumber) noexcept;
|
||||
|
||||
static void SetClockFormat (ClockFormat newClockFormat) noexcept;
|
||||
static void SetDateFormat (DateFormat newDateFormat) noexcept;
|
||||
|
||||
|
||||
|
||||
static void SetFileName (const std::string& logFileName) noexcept;
|
||||
static void SetDirectoryPath (const std::filesystem::path& logDirectoryPath) noexcept;
|
||||
|
||||
static void SetFlushTime (int seconds) noexcept;
|
||||
static void SetFlushTime (size_t seconds) noexcept { spdlog::flush_every(std::chrono::seconds(seconds)); }
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Creates a console and a file to log to.
|
||||
* @param[in] config The configuration parameters for the logger.
|
||||
*/
|
||||
static void Initialise (const Config& config = Config{});
|
||||
static void Shutdown () noexcept;
|
||||
|
||||
/**
|
||||
* @brief The next message logged by the logger will be set to follow the trivial pattern.
|
||||
*/
|
||||
static void UseTrivialPattern () noexcept;
|
||||
/**
|
||||
* @brief The next message logged by the logger will be set to follow the verbose pattern.
|
||||
*/
|
||||
static void UseVerbosePattern () noexcept;
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
static constexpr char DEFAULT_CONFIG_FLAG = 0b00011101; // 00011101
|
||||
static constexpr short DEFAULT_CONSOLE_LEN = 1024;
|
||||
|
||||
static unsigned char configFlags; // Initialised 0 0 FuncLine# FuncFileName Date TimeFormat Time
|
||||
static DateFormat dateFormat;
|
||||
|
||||
static std::string trivialPattern;
|
||||
static std::string verbosePattern;
|
||||
|
||||
static std::string fileName;
|
||||
static std::filesystem::path directoryPath; // For file logging
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
static bool CreateConsole ();
|
||||
static bool RedirectConsoleIO ();
|
||||
static bool DestroyConsole ();
|
||||
|
||||
static bool CheckInitialisation (const std::string_view& msg);
|
||||
static void UpdatePatterns ();
|
||||
static std::string BuildDateTimePattern();
|
||||
static std::string BuildVerbosePattern ();
|
||||
};
|
||||
|
||||
} // namespace SHADE
|
||||
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
/* Macros */
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define SHLOG_TRACE(format, ...) SHADE::SHLogger::UseTrivialPattern(); SPDLOG_LOGGER_TRACE(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__);
|
||||
#define SHLOGV_TRACE(format, ...) SHADE::SHLogger::UseVerbosePattern(); SPDLOG_LOGGER_TRACE(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__);
|
||||
#endif
|
||||
|
||||
#define SHLOG_INFO(format, ...) SHADE::SHLogger::UseTrivialPattern(); SPDLOG_LOGGER_INFO(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__);
|
||||
#define SHLOGV_INFO(format, ...) SHADE::SHLogger::UseVerbosePattern(); SPDLOG_LOGGER_INFO(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__);
|
||||
|
||||
#define SHLOG_WARNING(format, ...) SHADE::SHLogger::UseTrivialPattern(); SPDLOG_LOGGER_WARN(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__);
|
||||
#define SHLOGV_WARNING(format, ...) SHADE::SHLogger::UseVerbosePattern(); SPDLOG_LOGGER_WARN(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__);
|
||||
|
||||
#define SHLOG_ERROR(format, ...) SHADE::SHLogger::UseTrivialPattern(); SPDLOG_LOGGER_ERROR(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__);
|
||||
#define SHLOGV_ERROR(format, ...) SHADE::SHLogger::UseVerbosePattern(); SPDLOG_LOGGER_ERROR(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__);
|
||||
|
||||
#define SHLOG_CRITICAL(format, ...) SHADE::SHLogger::UseTrivialPattern(); SPDLOG_LOGGER_CRITICAL(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__);
|
||||
#define SHLOGV_CRITICAL(format, ...) SHADE::SHLogger::UseVerbosePattern(); SPDLOG_LOGGER_CRITICAL(spdlog::get(SHLOGGER_NAME), format, ## __VA_ARGS__);
|
||||
|
||||
// Misc Logging Macros
|
||||
#define SHLOG_FLOOR() SHADE::SHLogger::UseTrivialPattern(); SPDLOG_LOGGER_INFO(spdlog::get(SHLOGGER_NAME), "--------------------------------");
|
Loading…
Reference in New Issue