You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
253 lines
8.1 KiB
C++
253 lines
8.1 KiB
C++
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
|
|
#include "LogFile.h"
|
|
#include "LoggingComponent.h"
|
|
#include <AzCore/Serialization/SerializeContext.h>
|
|
#include <AzCore/Serialization/EditContext.h>
|
|
#include <AzCore/IO/FileIO.h>
|
|
#include <AzCore/Component/Entity.h>
|
|
#include <AzCore/Memory/Memory.h>
|
|
#include <AzFramework/StringFunc/StringFunc.h>
|
|
|
|
namespace AzFramework
|
|
{
|
|
namespace
|
|
{
|
|
const char* loggingHeaderString =
|
|
"/---------------------------------------------------------------------------\\\n";
|
|
const char* loggingHelloWorld =
|
|
"| ------------ AzFramework File Logging New Run----------------------------- |\n";
|
|
const char* loggingFooterString =
|
|
"\\---------------------------------------------------------------------------/\n\n";
|
|
|
|
const AZ::u64 defaultFileSize = 4 * 1024 * 1024;
|
|
const AZStd::string defaultPrefix = "AzFramework";
|
|
};
|
|
|
|
|
|
LogComponent::LogComponent()
|
|
: m_logFileBaseName(defaultPrefix)
|
|
, m_rolloverLength(defaultFileSize)
|
|
, m_logFile(nullptr)
|
|
{
|
|
}
|
|
|
|
LogComponent::~LogComponent()
|
|
{
|
|
DeactivateLogFile();
|
|
}
|
|
|
|
void LogComponent::Init()
|
|
{
|
|
}
|
|
|
|
|
|
void LogComponent::Activate()
|
|
{
|
|
ActivateLogFile();
|
|
AZ::Debug::TraceMessageBus::Handler::BusConnect();
|
|
}
|
|
|
|
void LogComponent::Deactivate()
|
|
{
|
|
AZ::Debug::TraceMessageBus::Handler::BusDisconnect();
|
|
DeactivateLogFile();
|
|
}
|
|
|
|
void LogComponent::ActivateLogFile()
|
|
{
|
|
// correction to faulty settings by restoring to defaults
|
|
if (m_logFileBaseName.length() <= 0)
|
|
{
|
|
m_logFileBaseName = defaultPrefix;
|
|
}
|
|
if (m_rolloverLength <= 0)
|
|
{
|
|
m_rolloverLength = defaultFileSize;
|
|
}
|
|
|
|
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
|
|
if (!fileIO)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const char* logDirectory = fileIO->GetAlias("@log@");
|
|
|
|
if (!logDirectory)
|
|
{
|
|
//We will not log anything if the log alias is not empty
|
|
AZ_Warning("Log Component", logDirectory, "Please set the log alias first, before trying to log data");
|
|
return;
|
|
}
|
|
|
|
m_logFile = aznew LogFile(logDirectory, m_logFileBaseName.c_str(), m_rolloverLength);
|
|
if (m_logFile)
|
|
{
|
|
m_logFile->SetMachineReadable(m_machineReadable);
|
|
m_logFile->AppendLog(LogFile::SEV_NORMAL, loggingHeaderString);
|
|
m_logFile->AppendLog(LogFile::SEV_NORMAL, loggingHelloWorld);
|
|
m_logFile->AppendLog(LogFile::SEV_NORMAL, loggingFooterString);
|
|
}
|
|
}
|
|
void LogComponent::DeactivateLogFile()
|
|
{
|
|
if (m_logFile)
|
|
{
|
|
delete m_logFile;
|
|
m_logFile = nullptr;
|
|
}
|
|
}
|
|
|
|
bool LogComponent::OnPrintf(const char* window, const char* message)
|
|
{
|
|
if (azstrnicmp(window, "debug", 5) == 0)
|
|
{
|
|
//If the window name contains the word debug than write the message only to the log file
|
|
//Our intention is to filter out anything sent to the "debug" window
|
|
//By returning true here, we override the default behavior of the trace system which would otherwise output it to stdout
|
|
OutputMessage(LogFile::SEV_DEBUG, window, message);
|
|
return true;
|
|
}
|
|
|
|
OutputMessage(LogFile::SEV_NORMAL, window, message);
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
bool LogComponent::OnAssert(const char* message)
|
|
{
|
|
OutputMessage(LogFile::SEV_ASSERT, "*ASSERT*", message);
|
|
|
|
return false;
|
|
}
|
|
|
|
bool LogComponent::OnWarning(const char* window, const char* message)
|
|
{
|
|
OutputMessage(LogFile::SEV_WARNING, window, message);
|
|
|
|
return false;
|
|
}
|
|
|
|
bool LogComponent::OnError(const char* window, const char* message)
|
|
{
|
|
OutputMessage(LogFile::SEV_ERROR, window, message);
|
|
|
|
return false;
|
|
}
|
|
|
|
bool LogComponent::OnException(const char* message)
|
|
{
|
|
OutputMessage(LogFile::SEV_EXCEPTION, "*EXCEPTION*", message);
|
|
|
|
return false;
|
|
}
|
|
|
|
void LogComponent::OutputMessage(LogFile::SeverityLevel severity, const char* window, const char* message)
|
|
{
|
|
if (m_logFile)
|
|
{
|
|
m_logFile->AppendLog(severity, window, message);
|
|
}
|
|
}
|
|
|
|
void LogComponent::Reflect(AZ::ReflectContext* context)
|
|
{
|
|
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
|
{
|
|
serializeContext->Class<LogComponent, AZ::Component>()
|
|
->Version(2)
|
|
->Field("Log FileBase Name", &LogComponent::m_logFileBaseName)
|
|
->Field("Log File Rollover Length", &LogComponent::m_rolloverLength)
|
|
->Field("MachineReadableMode", &LogComponent::m_machineReadable);
|
|
;
|
|
|
|
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
|
|
{
|
|
editContext->Class<LogComponent>(
|
|
"File Logging", "Listens to AZ trace messages and forwards them to a log file")
|
|
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
|
->Attribute(AZ::Edit::Attributes::Category, "Profiling")
|
|
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b))
|
|
->DataElement(AZ::Edit::UIHandlers::Default, &LogComponent::m_logFileBaseName, "Log file name", "The base name of the file to log to")
|
|
->DataElement(AZ::Edit::UIHandlers::SpinBox, &LogComponent::m_rolloverLength, "Rollover length", "Max size of a log file before saving and opening a new one")
|
|
->DataElement(AZ::Edit::UIHandlers::Default, &LogComponent::m_machineReadable, "Machine Readable", "")
|
|
;
|
|
}
|
|
}
|
|
}
|
|
|
|
void LogComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
|
|
{
|
|
provided.push_back(AZ_CRC("LoggingService", 0x64b9f716));
|
|
}
|
|
|
|
void LogComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
|
|
{
|
|
incompatible.push_back(AZ_CRC("LoggingService", 0x64b9f716));
|
|
}
|
|
|
|
void LogComponent::SetMachineReadable(bool newValue)
|
|
{
|
|
m_machineReadable = newValue;
|
|
bool isActive = ((this->GetEntity()) && (this->GetEntity()->GetState() == AZ::Entity::State::Active));
|
|
if (isActive)
|
|
{
|
|
//deactivate and activate the log file again on basename change
|
|
DeactivateLogFile();
|
|
ActivateLogFile();
|
|
}
|
|
}
|
|
|
|
void LogComponent::SetLogFileBaseName(const char* baseName)
|
|
{
|
|
if (AzFramework::StringFunc::Equal(m_logFileBaseName.c_str(), baseName, true))
|
|
{
|
|
return;
|
|
}
|
|
m_logFileBaseName = AZStd::string(baseName);
|
|
//Check to see whether the entity is active
|
|
bool isActive = ((this->GetEntity()) && (this->GetEntity()->GetState() == AZ::Entity::State::Active));
|
|
if (isActive)
|
|
{
|
|
//deactivate and activate the log file again on basename change
|
|
DeactivateLogFile();
|
|
ActivateLogFile();
|
|
}
|
|
}
|
|
|
|
void LogComponent::SetRollOverLength(AZ::u64 rolloverLength)
|
|
{
|
|
if (m_rolloverLength == rolloverLength)
|
|
{
|
|
return;
|
|
}
|
|
m_rolloverLength = rolloverLength;
|
|
//Check to see whether the entity is active
|
|
bool isActive = ((this->GetEntity()) && (this->GetEntity()->GetState() == AZ::Entity::State::Active));
|
|
if (isActive)
|
|
{
|
|
//deactivate and activate the log file again on rollover length change
|
|
DeactivateLogFile();
|
|
ActivateLogFile();
|
|
}
|
|
}
|
|
|
|
const char* LogComponent::GetLogFileBaseName()
|
|
{
|
|
return m_logFileBaseName.c_str();
|
|
}
|
|
|
|
AZ::u64 LogComponent::GetRollOverLength()
|
|
{
|
|
return m_rolloverLength;
|
|
}
|
|
};
|