2022-03-02 13:28:37 +00:00
|
|
|
#include "assertion_logger.h"
|
|
|
|
|
2023-11-10 20:49:42 +00:00
|
|
|
#include <base/lock.h>
|
2022-04-22 23:04:48 +00:00
|
|
|
#include <base/logger.h>
|
2022-03-02 13:28:37 +00:00
|
|
|
#include <base/system.h>
|
2023-11-10 20:49:42 +00:00
|
|
|
|
2022-04-22 23:04:48 +00:00
|
|
|
#include <engine/shared/ringbuffer.h>
|
|
|
|
#include <engine/storage.h>
|
|
|
|
|
|
|
|
class CAssertionLogger : public ILogger
|
2022-03-02 13:28:37 +00:00
|
|
|
{
|
2022-04-22 23:04:48 +00:00
|
|
|
struct SDebugMessageItem
|
|
|
|
{
|
|
|
|
char m_aMessage[1024];
|
|
|
|
};
|
|
|
|
|
2023-11-10 20:49:42 +00:00
|
|
|
CLock m_DbgMessageMutex;
|
2022-04-22 23:04:48 +00:00
|
|
|
CStaticRingBuffer<SDebugMessageItem, sizeof(SDebugMessageItem) * 64, CRingBufferBase::FLAG_RECYCLE> m_DbgMessages;
|
|
|
|
|
|
|
|
char m_aAssertLogPath[IO_MAX_PATH_LENGTH];
|
|
|
|
char m_aGameName[256];
|
|
|
|
|
2023-11-10 20:49:42 +00:00
|
|
|
void Dump() REQUIRES(!m_DbgMessageMutex);
|
|
|
|
|
2022-04-22 23:04:48 +00:00
|
|
|
public:
|
|
|
|
CAssertionLogger(const char *pAssertLogPath, const char *pGameName);
|
2023-11-10 20:49:42 +00:00
|
|
|
void Log(const CLogMessage *pMessage) override REQUIRES(!m_DbgMessageMutex);
|
|
|
|
void GlobalFinish() override REQUIRES(!m_DbgMessageMutex);
|
2022-04-22 23:04:48 +00:00
|
|
|
};
|
2022-03-02 13:28:37 +00:00
|
|
|
|
2022-04-22 23:04:48 +00:00
|
|
|
void CAssertionLogger::Log(const CLogMessage *pMessage)
|
2022-03-02 13:28:37 +00:00
|
|
|
{
|
2022-06-13 19:43:05 +00:00
|
|
|
if(m_Filter.Filters(pMessage))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2023-11-10 20:49:42 +00:00
|
|
|
const CLockScope LockScope(m_DbgMessageMutex);
|
2022-03-02 13:28:37 +00:00
|
|
|
SDebugMessageItem *pMsgItem = (SDebugMessageItem *)m_DbgMessages.Allocate(sizeof(SDebugMessageItem));
|
2022-07-09 16:14:56 +00:00
|
|
|
str_copy(pMsgItem->m_aMessage, pMessage->m_aLine);
|
2022-04-22 23:04:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CAssertionLogger::GlobalFinish()
|
|
|
|
{
|
|
|
|
if(dbg_assert_has_failed())
|
|
|
|
{
|
|
|
|
Dump();
|
|
|
|
}
|
2022-03-02 13:28:37 +00:00
|
|
|
}
|
|
|
|
|
2022-04-22 23:04:48 +00:00
|
|
|
void CAssertionLogger::Dump()
|
2022-03-02 13:28:37 +00:00
|
|
|
{
|
|
|
|
char aAssertLogFile[IO_MAX_PATH_LENGTH];
|
|
|
|
char aDate[64];
|
|
|
|
str_timestamp(aDate, sizeof(aDate));
|
2023-04-28 18:40:28 +00:00
|
|
|
str_format(aAssertLogFile, std::size(aAssertLogFile), "%s%s_assert_log_%s_%d.txt", m_aAssertLogPath, m_aGameName, aDate, pid());
|
2023-11-10 20:49:42 +00:00
|
|
|
const CLockScope LockScope(m_DbgMessageMutex);
|
2022-03-02 13:28:37 +00:00
|
|
|
IOHANDLE FileHandle = io_open(aAssertLogFile, IOFLAG_WRITE);
|
|
|
|
if(FileHandle)
|
|
|
|
{
|
|
|
|
auto *pIt = m_DbgMessages.First();
|
|
|
|
while(pIt)
|
|
|
|
{
|
|
|
|
io_write(FileHandle, pIt->m_aMessage, str_length(pIt->m_aMessage));
|
|
|
|
io_write(FileHandle, "\n", 1);
|
|
|
|
|
|
|
|
pIt = m_DbgMessages.Next(pIt);
|
|
|
|
}
|
|
|
|
|
|
|
|
io_sync(FileHandle);
|
|
|
|
io_close(FileHandle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-22 23:04:48 +00:00
|
|
|
CAssertionLogger::CAssertionLogger(const char *pAssertLogPath, const char *pGameName)
|
2022-03-02 13:28:37 +00:00
|
|
|
{
|
2022-07-09 16:14:56 +00:00
|
|
|
str_copy(m_aAssertLogPath, pAssertLogPath);
|
|
|
|
str_copy(m_aGameName, pGameName);
|
2022-04-22 23:04:48 +00:00
|
|
|
}
|
2022-03-02 13:28:37 +00:00
|
|
|
|
2022-04-22 23:04:48 +00:00
|
|
|
std::unique_ptr<ILogger> CreateAssertionLogger(IStorage *pStorage, const char *pGameName)
|
|
|
|
{
|
|
|
|
char aAssertLogPath[IO_MAX_PATH_LENGTH];
|
|
|
|
pStorage->GetCompletePath(IStorage::TYPE_SAVE, "dumps/", aAssertLogPath, sizeof(aAssertLogPath));
|
2022-05-28 12:46:53 +00:00
|
|
|
return std::make_unique<CAssertionLogger>(aAssertLogPath, pGameName);
|
2022-03-02 13:28:37 +00:00
|
|
|
}
|