Merge pull request #5820 from aws-lumberyard-dev/LYN-8025_PipeEditorServerLogsToEditor
Pipe Editor-Server Logs Back to the Editor
This commit is contained in:
+7
-6
@@ -6,16 +6,17 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "CommunicatorTracePrinter.h"
|
||||
#include "ProcessCommunicatorTracePrinter.h"
|
||||
|
||||
CommunicatorTracePrinter::CommunicatorTracePrinter(AzFramework::ProcessCommunicator* communicator, const char* window) :
|
||||
|
||||
ProcessCommunicatorTracePrinter::ProcessCommunicatorTracePrinter(AzFramework::ProcessCommunicator* communicator, const char* window) :
|
||||
m_communicator(communicator),
|
||||
m_window(window)
|
||||
{
|
||||
m_stringBeingConcatenated.reserve(1024);
|
||||
}
|
||||
|
||||
CommunicatorTracePrinter::~CommunicatorTracePrinter()
|
||||
ProcessCommunicatorTracePrinter::~ProcessCommunicatorTracePrinter()
|
||||
{
|
||||
// flush stdout
|
||||
WriteCurrentString(false);
|
||||
@@ -24,7 +25,7 @@ CommunicatorTracePrinter::~CommunicatorTracePrinter()
|
||||
WriteCurrentString(true);
|
||||
}
|
||||
|
||||
void CommunicatorTracePrinter::Pump()
|
||||
void ProcessCommunicatorTracePrinter::Pump()
|
||||
{
|
||||
if (m_communicator->IsValid())
|
||||
{
|
||||
@@ -42,7 +43,7 @@ void CommunicatorTracePrinter::Pump()
|
||||
}
|
||||
}
|
||||
|
||||
void CommunicatorTracePrinter::ParseDataBuffer(AZ::u32 readSize, bool isFromStdErr)
|
||||
void ProcessCommunicatorTracePrinter::ParseDataBuffer(AZ::u32 readSize, bool isFromStdErr)
|
||||
{
|
||||
if (readSize > AZ_ARRAY_SIZE(m_streamBuffer))
|
||||
{
|
||||
@@ -67,7 +68,7 @@ void CommunicatorTracePrinter::ParseDataBuffer(AZ::u32 readSize, bool isFromStdE
|
||||
}
|
||||
}
|
||||
|
||||
void CommunicatorTracePrinter::WriteCurrentString(bool isFromStdErr)
|
||||
void ProcessCommunicatorTracePrinter::WriteCurrentString(bool isFromStdErr)
|
||||
{
|
||||
AZStd::string& bufferToUse = isFromStdErr ? m_errorStringBeingConcatenated : m_stringBeingConcatenated;
|
||||
|
||||
+7
-6
@@ -10,20 +10,21 @@
|
||||
|
||||
#include <AzFramework/Process/ProcessCommunicator.h>
|
||||
|
||||
//! CommunicatorTracePrinter listens to stderr and stdout of a running process and writes its output to the AZ_Trace system
|
||||
//! ProcessCommunicatorTracePrinter listens to stderr and stdout of a running process and writes its output to the AZ_Trace system
|
||||
//! Importantly, it does not do any blocking operations.
|
||||
class CommunicatorTracePrinter
|
||||
class ProcessCommunicatorTracePrinter
|
||||
{
|
||||
public:
|
||||
CommunicatorTracePrinter(AzFramework::ProcessCommunicator* communicator, const char* window);
|
||||
~CommunicatorTracePrinter();
|
||||
ProcessCommunicatorTracePrinter(AzFramework::ProcessCommunicator* communicator, const char* window);
|
||||
~ProcessCommunicatorTracePrinter();
|
||||
|
||||
// call this periodically to drain the buffers and write them.
|
||||
//! Call this periodically to drain the buffers and write them.
|
||||
void Pump();
|
||||
|
||||
// drains the buffer into the string thats being built, then traces the string when it hits a newline.
|
||||
//! Drains the buffer into the string that's being built, then traces the string when it hits a newline.
|
||||
void ParseDataBuffer(AZ::u32 readSize, bool isFromStdErr);
|
||||
|
||||
//! Prints the current buffer to AZ_Error or AZ_TracePrintf so that it can be picked up by AZ::Debug::Trace
|
||||
void WriteCurrentString(bool isFromStdError);
|
||||
|
||||
private:
|
||||
@@ -277,6 +277,8 @@ set(FILES
|
||||
Process/ProcessWatcher.cpp
|
||||
Process/ProcessWatcher.h
|
||||
Process/ProcessCommon_fwd.h
|
||||
Process/ProcessCommunicatorTracePrinter.cpp
|
||||
Process/ProcessCommunicatorTracePrinter.h
|
||||
ProjectManager/ProjectManager.h
|
||||
ProjectManager/ProjectManager.cpp
|
||||
Render/GameIntersectorComponent.h
|
||||
|
||||
@@ -71,6 +71,14 @@ public:
|
||||
// The value of the argument as integer number.
|
||||
virtual const int GetIValue() const = 0;
|
||||
// </interfuscator:shuffle>
|
||||
|
||||
// Description:
|
||||
// Retrieve the value of the argument.
|
||||
// Arguments:
|
||||
// cmdLineValue. The cmdline value will be filled out if a valid boolean is found.
|
||||
// Return Value:
|
||||
// Returns true if the cmdline arg is actually a boolean string matching "true" or "false"; otherwise return false.
|
||||
virtual const bool GetBoolValue(bool& cmdLineValue) const = 0;
|
||||
};
|
||||
|
||||
// Command line interface
|
||||
|
||||
@@ -36,9 +36,10 @@ public:
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
inline static void Connect()
|
||||
inline static void Connect(bool suppressSystemOutput)
|
||||
{
|
||||
GetInstance().m_ignoredAsserts = new IgnoredAssertMap();
|
||||
GetInstance().m_suppressSystemOutput = suppressSystemOutput;
|
||||
GetInstance().BusConnect();
|
||||
}
|
||||
|
||||
@@ -126,7 +127,7 @@ public:
|
||||
CryLogAlways("%s", message);
|
||||
}
|
||||
|
||||
return true; // suppress default AzCore behavior.
|
||||
return m_suppressSystemOutput;
|
||||
#else
|
||||
AZ_UNUSED(fileName);
|
||||
AZ_UNUSED(line);
|
||||
@@ -146,7 +147,7 @@ public:
|
||||
return false; // allow AZCore to do its default behavior.
|
||||
}
|
||||
gEnv->pLog->LogError("(%s) - %s", window, message);
|
||||
return true; // suppress default AzCore behavior.
|
||||
return m_suppressSystemOutput;
|
||||
}
|
||||
|
||||
bool OnPreWarning(const char* window, const char* fileName, int line, const char* func, const char* message) override
|
||||
@@ -161,7 +162,7 @@ public:
|
||||
}
|
||||
|
||||
CryWarning(VALIDATOR_MODULE_UNKNOWN, VALIDATOR_WARNING, "(%s) - %s", window, message);
|
||||
return true; // suppress default AzCore behavior.
|
||||
return m_suppressSystemOutput;
|
||||
}
|
||||
|
||||
bool OnOutput(const char* window, const char* message) override
|
||||
@@ -179,12 +180,13 @@ public:
|
||||
{
|
||||
CryLog("(%s) - %s", window, message);
|
||||
}
|
||||
|
||||
return true; // suppress default AzCore behavior.
|
||||
|
||||
return m_suppressSystemOutput;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
using IgnoredAssertMap = AZStd::unordered_map<AZ::Crc32, bool, AZStd::hash<AZ::Crc32>, AZStd::equal_to<AZ::Crc32>, AZ::OSStdAllocator>;
|
||||
IgnoredAssertMap* m_ignoredAsserts;
|
||||
bool m_suppressSystemOutput = true;
|
||||
};
|
||||
|
||||
@@ -42,5 +42,22 @@ const int CCmdLineArg::GetIValue() const
|
||||
{
|
||||
return atoi(m_value.c_str());
|
||||
}
|
||||
const bool CCmdLineArg::GetBoolValue(bool& cmdLineValue) const
|
||||
{
|
||||
AZStd::string lowercaseValue(m_value);
|
||||
AZStd::to_lower(lowercaseValue.begin(), lowercaseValue.end());
|
||||
if (lowercaseValue == "true")
|
||||
{
|
||||
cmdLineValue = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lowercaseValue == "false")
|
||||
{
|
||||
cmdLineValue = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ public:
|
||||
const ECmdLineArgType GetType() const;
|
||||
const float GetFValue() const;
|
||||
const int GetIValue() const;
|
||||
const bool GetBoolValue(bool& cmdLineValue) const;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -737,7 +737,17 @@ bool CSystem::Init(const SSystemInitParams& startupParams)
|
||||
|
||||
m_pCmdLine = new CCmdLine(startupParams.szSystemCmdLine);
|
||||
|
||||
AZCoreLogSink::Connect();
|
||||
// Init AZCoreLogSink. Don't suppress system output if we're running as an editor-server
|
||||
bool suppressSystemOutput = true;
|
||||
if (const ICmdLineArg* isEditorServerArg = m_pCmdLine->FindArg(eCLAT_Pre, "editorsv_isDedicated"))
|
||||
{
|
||||
bool editorsv_isDedicated = false;
|
||||
if (isEditorServerArg->GetBoolValue(editorsv_isDedicated) && editorsv_isDedicated)
|
||||
{
|
||||
suppressSystemOutput = false;
|
||||
}
|
||||
}
|
||||
AZCoreLogSink::Connect(suppressSystemOutput);
|
||||
|
||||
// Registers all AZ Console Variables functors specified within CrySystem
|
||||
if (auto azConsole = AZ::Interface<AZ::IConsole>::Get(); azConsole)
|
||||
|
||||
@@ -92,8 +92,6 @@ set(FILES
|
||||
native/utilities/BuilderManager.inl
|
||||
native/utilities/ByteArrayStream.cpp
|
||||
native/utilities/ByteArrayStream.h
|
||||
native/utilities/CommunicatorTracePrinter.cpp
|
||||
native/utilities/CommunicatorTracePrinter.h
|
||||
native/utilities/IniConfiguration.cpp
|
||||
native/utilities/IniConfiguration.h
|
||||
native/utilities/JobDiagnosticTracker.cpp
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
#include <AzFramework/Application/Application.h>
|
||||
|
||||
#include <AzFramework/Process/ProcessCommunicator.h>
|
||||
#include <AzFramework/Process/ProcessWatcher.h>
|
||||
#include <AzToolsFramework/Application/ToolsApplication.h>
|
||||
|
||||
@@ -31,7 +30,6 @@
|
||||
|
||||
#include "native/utilities/assetUtils.h"
|
||||
#include "native/utilities/AssetBuilderInfo.h"
|
||||
#include "native/utilities/CommunicatorTracePrinter.h"
|
||||
|
||||
#include <AssetProcessor_Traits_Platform.h>
|
||||
|
||||
|
||||
@@ -1482,7 +1482,7 @@ bool ApplicationManagerBase::WaitForBuilderExit(AzFramework::ProcessWatcher* pro
|
||||
AZ::u32 exitCode = 0;
|
||||
bool finishedOK = false;
|
||||
QElapsedTimer ticker;
|
||||
CommunicatorTracePrinter tracer(processWatcher->GetCommunicator(), "AssetBuilder");
|
||||
ProcessCommunicatorTracePrinter tracer(processWatcher->GetCommunicator(), "AssetBuilder");
|
||||
|
||||
ticker.start();
|
||||
|
||||
|
||||
@@ -164,7 +164,7 @@ namespace AssetProcessor
|
||||
return false;
|
||||
}
|
||||
|
||||
m_tracePrinter = AZStd::make_unique<CommunicatorTracePrinter>(m_processWatcher->GetCommunicator(), "AssetBuilder");
|
||||
m_tracePrinter = AZStd::make_unique<ProcessCommunicatorTracePrinter>(m_processWatcher->GetCommunicator(), "AssetBuilder");
|
||||
|
||||
return WaitForConnection();
|
||||
}
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/std/parallel/binary_semaphore.h>
|
||||
#include <AzFramework/Process/ProcessWatcher.h>
|
||||
#include <AzFramework/Process/ProcessCommunicatorTracePrinter.h>
|
||||
#include <AssetBuilderSDK/AssetBuilderSDK.h>
|
||||
#include <AzCore/std/smart_ptr/shared_ptr.h>
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
#include <native/utilities/CommunicatorTracePrinter.h>
|
||||
#include <native/utilities/assetUtils.h>
|
||||
#include <QDir> // used in the inl file.
|
||||
|
||||
@@ -127,7 +127,7 @@ namespace AssetProcessor
|
||||
AZStd::unique_ptr<AzFramework::ProcessWatcher> m_processWatcher = nullptr;
|
||||
|
||||
//! Optional communicator, only available if we have a process watcher
|
||||
AZStd::unique_ptr<CommunicatorTracePrinter> m_tracePrinter = nullptr;
|
||||
AZStd::unique_ptr<ProcessCommunicatorTracePrinter> m_tracePrinter = nullptr;
|
||||
|
||||
const AssetUtilities::QuitListener& m_quitListener;
|
||||
};
|
||||
|
||||
@@ -14,11 +14,8 @@
|
||||
#include <MultiplayerSystemComponent.h>
|
||||
#include <PythonEditorEventsBus.h>
|
||||
#include <Editor/MultiplayerEditorSystemComponent.h>
|
||||
#include <Source/AutoGen/Multiplayer.AutoPackets.h>
|
||||
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <AzCore/Console/ILogger.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
@@ -133,6 +130,7 @@ namespace Multiplayer
|
||||
AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect();
|
||||
AzFramework::GameEntityContextEventBus::Handler::BusDisconnect();
|
||||
MultiplayerEditorServerRequestBus::Handler::BusDisconnect();
|
||||
AZ::TickBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void MultiplayerEditorSystemComponent::NotifyRegisterViews()
|
||||
@@ -157,12 +155,20 @@ namespace Multiplayer
|
||||
[[fallthrough]];
|
||||
case eNotify_OnEndGameMode:
|
||||
// Kill the configured server if it's active
|
||||
if (m_serverProcess)
|
||||
AZ::TickBus::Handler::BusDisconnect();
|
||||
if (m_serverProcessWatcher)
|
||||
{
|
||||
m_serverProcess->TerminateProcess(0);
|
||||
m_serverProcess = nullptr;
|
||||
m_serverProcessWatcher->TerminateProcess(0);
|
||||
if (m_serverProcessTracePrinter)
|
||||
{
|
||||
m_serverProcessTracePrinter->Pump();
|
||||
m_serverProcessTracePrinter->WriteCurrentString(true);
|
||||
m_serverProcessTracePrinter->WriteCurrentString(false);
|
||||
}
|
||||
m_serverProcessWatcher = nullptr;
|
||||
m_serverProcessTracePrinter = nullptr;
|
||||
}
|
||||
|
||||
|
||||
if (INetworkInterface* editorNetworkInterface = AZ::Interface<INetworking>::Get()->RetrieveNetworkInterface(AZ::Name(MpEditorInterfaceName)))
|
||||
{
|
||||
editorNetworkInterface->Disconnect(m_editorConnId, AzNetworking::DisconnectReason::TerminatedByClient);
|
||||
@@ -181,7 +187,7 @@ namespace Multiplayer
|
||||
}
|
||||
}
|
||||
|
||||
AzFramework::ProcessWatcher* LaunchEditorServer()
|
||||
void MultiplayerEditorSystemComponent::LaunchEditorServer()
|
||||
{
|
||||
// Assemble the server's path
|
||||
AZ::CVarFixedString serverProcess = editorsv_process;
|
||||
@@ -207,12 +213,22 @@ namespace Multiplayer
|
||||
{
|
||||
server_rhi = static_cast<AZ::CVarFixedString>(editorsv_rhi_override);
|
||||
}
|
||||
|
||||
const auto console = AZ::Interface<AZ::IConsole>::Get();
|
||||
AZ::CVarFixedString sv_defaultPlayerSpawnAsset;
|
||||
|
||||
if (console->GetCvarValue("sv_defaultPlayerSpawnAsset", sv_defaultPlayerSpawnAsset) != AZ::GetValueResult::Success)
|
||||
{
|
||||
AZ_Assert( false,
|
||||
"MultiplayerEditorSystemComponent::LaunchEditorServer failed! Could not find the sv_defaultPlayerSpawnAsset cvar; the editor-server "
|
||||
"will fall back to using some other default player! Please update this code to use a valid cvar!")
|
||||
}
|
||||
|
||||
processLaunchInfo.m_commandlineParameters = AZStd::string::format(
|
||||
R"("%s" --project-path "%s" --editorsv_isDedicated true --sv_defaultPlayerSpawnAsset "%s" --rhi "%s")",
|
||||
serverPath.c_str(),
|
||||
AZ::Utils::GetProjectPath().c_str(),
|
||||
static_cast<AZ::CVarFixedString>(sv_defaultPlayerSpawnAsset).c_str(),
|
||||
sv_defaultPlayerSpawnAsset.c_str(),
|
||||
server_rhi.GetCStr()
|
||||
);
|
||||
processLaunchInfo.m_showWindow = true;
|
||||
@@ -220,13 +236,21 @@ namespace Multiplayer
|
||||
|
||||
// Launch the Server
|
||||
AzFramework::ProcessWatcher* outProcess = AzFramework::ProcessWatcher::LaunchProcess(
|
||||
processLaunchInfo, AzFramework::ProcessCommunicationType::COMMUNICATOR_TYPE_NONE);
|
||||
processLaunchInfo, AzFramework::ProcessCommunicationType::COMMUNICATOR_TYPE_STDINOUT);
|
||||
|
||||
AZ_Error(
|
||||
"MultiplayerEditor", processLaunchInfo.m_launchResult != AzFramework::ProcessLauncher::ProcessLaunchResult::PLR_MissingFile,
|
||||
"LaunchEditorServer failed! The ServerLauncher binary is missing! (%s) Please build server launcher.", serverPath.c_str())
|
||||
|
||||
return outProcess;
|
||||
// Stop the previous server if one exists
|
||||
if (m_serverProcessWatcher)
|
||||
{
|
||||
AZ::TickBus::Handler::BusDisconnect();
|
||||
m_serverProcessWatcher->TerminateProcess(0);
|
||||
}
|
||||
m_serverProcessWatcher.reset(outProcess);
|
||||
m_serverProcessTracePrinter = AZStd::make_unique<ProcessCommunicatorTracePrinter>(m_serverProcessWatcher->GetCommunicator(), "EditorServer");
|
||||
AZ::TickBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
void MultiplayerEditorSystemComponent::OnGameEntitiesStarted()
|
||||
@@ -286,7 +310,7 @@ namespace Multiplayer
|
||||
editorNetworkInterface->Listen(editorsv_port);
|
||||
|
||||
// Launch the editor-server
|
||||
m_serverProcess = LaunchEditorServer();
|
||||
LaunchEditorServer();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -393,4 +417,20 @@ namespace Multiplayer
|
||||
{
|
||||
return PyIsInGameMode();
|
||||
}
|
||||
|
||||
void MultiplayerEditorSystemComponent::OnTick(float, AZ::ScriptTimePoint)
|
||||
{
|
||||
if (m_serverProcessTracePrinter)
|
||||
{
|
||||
m_serverProcessTracePrinter->Pump();
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ::TickBus::Handler::BusDisconnect();
|
||||
AZ_Warning(
|
||||
"MultiplayerEditorSystemComponent", false,
|
||||
"The server process trace printer is NULL so we won't be able to pipe server logs to the editor. Please update the code to call AZ::TickBus::Handler::BusDisconnect whenever the editor-server is terminated.")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,14 +13,12 @@
|
||||
#include <Multiplayer/Editor/MultiplayerPythonEditorEventsBus.h>
|
||||
#include <IEditor.h>
|
||||
|
||||
#include <Editor/MultiplayerEditorConnection.h>
|
||||
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <AzCore/Console/ILogger.h>
|
||||
#include <AzFramework/Entity/GameEntityContextBus.h>
|
||||
#include <AzFramework/Process/ProcessWatcher.h>
|
||||
#include <AzFramework/Process/ProcessCommunicatorTracePrinter.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
|
||||
|
||||
namespace AzNetworking
|
||||
@@ -52,6 +50,7 @@ namespace Multiplayer
|
||||
, private AzToolsFramework::EditorEvents::Bus::Handler
|
||||
, private IEditorNotifyListener
|
||||
, private MultiplayerEditorServerRequestBus::Handler
|
||||
, private AZ::TickBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(MultiplayerEditorSystemComponent, "{9F335CC0-5574-4AD3-A2D8-2FAEF356946C}");
|
||||
@@ -84,7 +83,9 @@ namespace Multiplayer
|
||||
bool IsInGameMode() override;
|
||||
//! @}
|
||||
|
||||
private:
|
||||
private:
|
||||
void LaunchEditorServer();
|
||||
|
||||
//! EditorEvents::Handler overrides
|
||||
//! @{
|
||||
void OnEditorNotifyEvent(EEditorNotifyEvent event) override;
|
||||
@@ -101,8 +102,14 @@ namespace Multiplayer
|
||||
void SendEditorServerLevelDataPacket(AzNetworking::IConnection* connection) override;
|
||||
//! @}
|
||||
|
||||
//! AZ::TickBus::Handler
|
||||
//! @{
|
||||
void OnTick(float, AZ::ScriptTimePoint) override;
|
||||
//! @}
|
||||
|
||||
IEditor* m_editor = nullptr;
|
||||
AzFramework::ProcessWatcher* m_serverProcess = nullptr;
|
||||
AZStd::unique_ptr<AzFramework::ProcessWatcher> m_serverProcessWatcher = nullptr;
|
||||
AZStd::unique_ptr<ProcessCommunicatorTracePrinter> m_serverProcessTracePrinter = nullptr;
|
||||
AzNetworking::ConnectionId m_editorConnId;
|
||||
|
||||
ServerAcceptanceReceivedEvent::Handler m_serverAcceptanceReceivedHandler;
|
||||
|
||||
@@ -37,8 +37,6 @@ namespace AzNetworking
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
AZ_CVAR_EXTERNED(AZ::CVarFixedString, sv_defaultPlayerSpawnAsset);
|
||||
|
||||
//! Multiplayer system component wraps the bridging logic between the game and transport layer.
|
||||
class MultiplayerSystemComponent final
|
||||
: public AZ::Component
|
||||
|
||||
Reference in New Issue
Block a user