From 3f8ede1f8c773ec509fda430e975459606d859e2 Mon Sep 17 00:00:00 2001 From: shegazyy Date: Mon, 7 Sep 2026 16:47:31 +0300 Subject: [PATCH 1/3] fix(process_group_manager): standardize ProcessInfoNode logs (#570) Add a private logId() helper that renders a consistent identity string, "Name: , PID: ", and use it at all 19 call sites in ProcessInfoNode that previously formatted process identity differently ("process X", "process (X)", "process X pid Y", "pid Y (X)", ...). Also fixes a bug at startProcess(): a log statement streamed the raw 'this' pointer instead of process identity, which prints as "1"/"true" under the fallback console logger instead of anything useful. Two logs that previously omitted process identity entirely (file-wait error, PID-map insertion failure) now include it too. --- .../details/process_info_node.cpp | 53 +++++++++++-------- .../details/process_info_node.hpp | 4 ++ 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp index 4c3aacab1..ce29c082d 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp @@ -20,6 +20,7 @@ #include #include #include +#include namespace score::mw::lifecycle::internal { @@ -46,18 +47,18 @@ ProcessInfoNode::ProcessInfoNode(configuration::ComponentConfig&& config, Proces app_profile.alive_supervision.has_value(), "Supervised process did not have alive supervision config"); const uid_t uid = config_.deployment_config.sandbox.uid; - LM_LOG_DEBUG() << "Setting up alive supervision for" << identifier_; + LM_LOG_DEBUG() << "Setting up alive supervision for" << logId(); supervision_handle_ = process_handling_.supervision_factory.constructSupervision( identifier_, uid, app_profile.alive_supervision.value()); if (!supervision_handle_) { - LM_LOG_ERROR() << "Failed to set up alive supervision for" << identifier_; + LM_LOG_ERROR() << "Failed to set up alive supervision for" << logId(); } else { - LM_LOG_DEBUG() << "Successfully set up alive supervision for" << identifier_; + LM_LOG_DEBUG() << "Successfully set up alive supervision for" << logId(); } config_.deployment_config.environmental_variables.add( @@ -174,7 +175,7 @@ void ProcessInfoNode::unblockSync() IComponent::RequestResult ProcessInfoNode::tryHandleTermination(int32_t process_status) { - LM_LOG_DEBUG() << "Process" << identifier_ << "( pid" << pid_ << ") terminated with exit code" << process_status; + LM_LOG_DEBUG() << logId() << "terminated with exit code" << process_status; exit_code_ = process_status; IComponent::RequestResult res = {IComponent::RequestState::kWaiting}; ProcessState starting = ProcessState::kStarting; @@ -212,8 +213,7 @@ IComponent::RequestResult ProcessInfoNode::tryHandleTermination(int32_t process_ } else { - LM_LOG_WARN() << "unexpected termination of process" << identifier_ << "( pid" << pid_ << "exit code" - << exit_code_ << ")"; + LM_LOG_WARN() << "Unexpected termination of" << logId() << "exit code" << exit_code_; res = score::cpp::make_unexpected(IComponent::ComponentError::kErrorAfterReady); } } @@ -241,8 +241,8 @@ bool ProcessInfoNode::isSupervised() const IComponent::RequestResult ProcessInfoNode::startProcess(score::cpp::stop_token stop_token) { - LM_LOG_DEBUG() << "Starting process (" << identifier_ << ") from executable" << config_.deployment_config.bin_dir - << "/" << config_.component_properties.binary_name; + LM_LOG_DEBUG() << "Starting" << logId() << "from executable" << config_.deployment_config.bin_dir << "/" + << config_.component_properties.binary_name; std::optional error; const std::chrono::time_point initial_time = std::chrono::steady_clock::now(); @@ -258,7 +258,7 @@ IComponent::RequestResult ProcessInfoNode::startProcess(score::cpp::stop_token s // - Terminating: A termination is in progress (allowed) if (!setState(score::mw::lifecycle::ProcessState::kIdle)) { - LM_LOG_WARN() << "Starting process" << this << "failed: termination in progress"; + LM_LOG_WARN() << "Starting" << logId() << "failed: termination in progress"; error = ComponentError::kErrorBeforeReady; break; } @@ -272,8 +272,8 @@ IComponent::RequestResult ProcessInfoNode::startProcess(score::cpp::stop_token s if (osal::OsalReturnType::kSuccess == process_handling_.process_interface_->startProcess(pid_, sync_, config_)) { const std::chrono::time_point launched_time = std::chrono::steady_clock::now(); - LM_LOG_DEBUG() << "startProcess pid" << pid_ << "received for process:" << identifier_ << "( startup time:" - << std::chrono::round(launched_time - initial_time) << ")"; + LM_LOG_DEBUG() << logId() << "started, startup time:" + << std::chrono::round(launched_time - initial_time); if (configuration::ApplicationType::StateManager == config_.component_properties.application_profile.application_type) @@ -308,7 +308,7 @@ IComponent::RequestResult ProcessInfoNode::startProcess(score::cpp::stop_token s sync_.reset(); } const std::chrono::time_point finished_time = std::chrono::steady_clock::now(); - LM_LOG_DEBUG() << "startProcess for process (" << config_.name << ") done, took" + LM_LOG_DEBUG() << "startProcess for" << logId() << "done, took" << std::chrono::round(finished_time - initial_time); if (error.has_value()) @@ -360,6 +360,13 @@ void ProcessInfoNode::setupControlClientChannel() std::atomic_store(&control_client_channel_, ControlClientChannel::getControlClientChannel(sync_)); } +std::string ProcessInfoNode::logId() const +{ + std::ostringstream oss; + oss << "Name: " << identifier_ << ", PID: " << pid_; + return oss.str(); +} + score::cpp::expected_blank ProcessInfoNode::handleProcessStillStarting( const score::cpp::stop_token& stop_token) { @@ -400,7 +407,7 @@ score::cpp::expected_blank ProcessInfoNode::handlePr if (wait_res != osal::OsalReturnType::kSuccess) { - LM_LOG_ERROR() << "Error Waiting for file"; + LM_LOG_ERROR() << "Error waiting for file for" << logId(); } return (wait_res == osal::OsalReturnType::kSuccess) && (exit_code_ == 0); @@ -419,7 +426,7 @@ score::cpp::expected_blank ProcessInfoNode::handlePr return score::cpp::make_unexpected(ComponentError::kErrorBeforeReady); } - LM_LOG_WARN() << "Got kRunning timeout for process (" << identifier_ << ")"; + LM_LOG_WARN() << "Got kRunning timeout for" << logId(); terminateProcess(stop_token); return score::cpp::make_unexpected(ComponentError::kActivationTimedOut); } @@ -450,7 +457,7 @@ ProcessInfoNode::handleProcessStarted(const score::cpp::stop_token& stop_token) return handleProcessAlreadyTerminated(); default: // Error case when pn == -1 // really bad fatal error, should not happen, treat as a failure to set the state & kill the process - LM_LOG_ERROR() << "Could not add PID to map!"; + LM_LOG_ERROR() << "Could not add" << logId() << "to process map!"; terminateProcess(stop_token); return score::cpp::make_unexpected(ComponentError::kErrorBeforeReady); } @@ -460,37 +467,37 @@ void ProcessInfoNode::handleProcessRunning() { if (!isReporting()) { - LM_LOG_DEBUG() << "Considered kRunning for Non Reporting Process pid" << pid_ << "(" << identifier_ << ")"; + LM_LOG_DEBUG() << "Considered kRunning for non-reporting" << logId(); } else { - LM_LOG_DEBUG() << "Got kRunning for pid" << pid_ << "(" << identifier_ << ")"; + LM_LOG_DEBUG() << "Got kRunning for" << logId(); } } void ProcessInfoNode::terminateProcess(const score::cpp::stop_token& stop_token) { - LM_LOG_DEBUG() << "terminating process (" << identifier_ << ")"; + LM_LOG_DEBUG() << "Terminating" << logId(); if (setState(score::mw::lifecycle::ProcessState::kTerminating)) { handleTerminationProcess(stop_token); } - LM_LOG_DEBUG() << "terminateProcess for process (" << identifier_ << ") done"; + LM_LOG_DEBUG() << "terminateProcess for" << logId() << "done"; } void ProcessInfoNode::handleTerminationProcess(const score::cpp::stop_token& stop_token) { static_cast(terminator_.init(0U, false)); has_semaphore_.store(true); - LM_LOG_DEBUG() << "Requesting termination of process pid" << pid_ << "(" << identifier_ << ")"; + LM_LOG_DEBUG() << "Requesting termination of" << logId(); // handle request termination if ((process_handling_.process_interface_->requestTermination(pid_) == osal::OsalReturnType::kFail) || (terminator_.timedWait(std::chrono::milliseconds(config_.deployment_config.shutdown_timeout_ms)) == osal::OsalReturnType::kSuccess)) { - LM_LOG_DEBUG() << "Queuing jobs after regular termination of process (" << identifier_ << ")"; + LM_LOG_DEBUG() << "Queuing jobs after regular termination of" << logId(); } else { @@ -506,12 +513,12 @@ void ProcessInfoNode::handleForcedTermination(const score::cpp::stop_token& stop { static_cast(stop_token); // Not yet supported - LM_LOG_WARN() << "Process (" << identifier_ << ") did not respond to SIGTERM, sending SIGKILL"; + LM_LOG_WARN() << logId() << "did not respond to SIGTERM, sending SIGKILL"; while ((osal::OsalReturnType::kSuccess == process_handling_.process_interface_->forceTermination(pid_)) && (terminator_.timedWait(score::mw::lifecycle::internal::kMaxSigKillDelay) != osal::OsalReturnType::kSuccess)) { - LM_LOG_FATAL() << "Process (" << identifier_ << ") did not respond to SIGKILL!!"; + LM_LOG_FATAL() << logId() << "did not respond to SIGKILL!!"; } } diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.hpp b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.hpp index b13407650..8eebb555d 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.hpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.hpp @@ -25,6 +25,7 @@ #include #include #include +#include namespace score::mw::lifecycle::internal { @@ -173,6 +174,9 @@ class ProcessInfoNode final : public IComponent /// @brief Creates the ControlClientChannel from the process's IPC comms handle. void setupControlClientChannel(); + /// @brief Returns a standardized identity string for logging, e.g. "Name: my_component, PID: 1234". + [[nodiscard]] std::string logId() const; + /// @brief semaphore used to check termination with timeout osal::Semaphore terminator_{}; From d783f27a01512dbfc6e61285e6f738e0796734b3 Mon Sep 17 00:00:00 2001 From: shegazyy Date: Mon, 14 Sep 2026 12:59:43 +0300 Subject: [PATCH 2/3] Address review: allocation-free logId(), consistent order Per review feedback (NicolasFussberger): logId() returned std::string, heap-allocating on every log call, which must be avoided after initialization. - logId() now returns ProcessLogId, a small trivially-copyable struct (IdentifierHash + osal::ProcessID) instead of building a std::string. Formatting happens only when a log line is actually printed, via operator<< overloads for both std::ostream and score::mw::log::LogStream (mirroring the exact dual-overload pattern IdentifierHash already uses for the two supported logging backends). No heap allocation. Per review feedback (danth): for readability, the process identity should consistently lead every log message rather than appearing in the middle or at the end. - Reordered all 19 call sites so every one now reads `LM_LOG_*() << logId() << "";`, replacing the previous mixed styles ("Setting up alive supervision for" << logId(), "Starting" << logId() << "from executable" ..., etc.). --- .../details/process_info_node.cpp | 58 ++++++++++++------- .../details/process_info_node.hpp | 31 +++++++++- 2 files changed, 65 insertions(+), 24 deletions(-) diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp index ce29c082d..718ef511f 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp @@ -20,11 +20,15 @@ #include #include #include -#include namespace score::mw::lifecycle::internal { +std::ostream& operator<<(std::ostream& os, const ProcessLogId& id) +{ + return os << "Name: " << id.identifier << ", PID: " << id.pid; +} + ProcessInfoNode::ProcessInfoNode(configuration::ComponentConfig&& config, ProcessHandling process_handling) : terminator_(), has_semaphore_(false), @@ -47,18 +51,18 @@ ProcessInfoNode::ProcessInfoNode(configuration::ComponentConfig&& config, Proces app_profile.alive_supervision.has_value(), "Supervised process did not have alive supervision config"); const uid_t uid = config_.deployment_config.sandbox.uid; - LM_LOG_DEBUG() << "Setting up alive supervision for" << logId(); + LM_LOG_DEBUG() << logId() << "setting up alive supervision"; supervision_handle_ = process_handling_.supervision_factory.constructSupervision( identifier_, uid, app_profile.alive_supervision.value()); if (!supervision_handle_) { - LM_LOG_ERROR() << "Failed to set up alive supervision for" << logId(); + LM_LOG_ERROR() << logId() << "failed to set up alive supervision"; } else { - LM_LOG_DEBUG() << "Successfully set up alive supervision for" << logId(); + LM_LOG_DEBUG() << logId() << "successfully set up alive supervision"; } config_.deployment_config.environmental_variables.add( @@ -213,7 +217,7 @@ IComponent::RequestResult ProcessInfoNode::tryHandleTermination(int32_t process_ } else { - LM_LOG_WARN() << "Unexpected termination of" << logId() << "exit code" << exit_code_; + LM_LOG_WARN() << logId() << "unexpected termination, exit code" << exit_code_; res = score::cpp::make_unexpected(IComponent::ComponentError::kErrorAfterReady); } } @@ -241,7 +245,7 @@ bool ProcessInfoNode::isSupervised() const IComponent::RequestResult ProcessInfoNode::startProcess(score::cpp::stop_token stop_token) { - LM_LOG_DEBUG() << "Starting" << logId() << "from executable" << config_.deployment_config.bin_dir << "/" + LM_LOG_DEBUG() << logId() << "starting from executable" << config_.deployment_config.bin_dir << "/" << config_.component_properties.binary_name; std::optional error; @@ -258,7 +262,7 @@ IComponent::RequestResult ProcessInfoNode::startProcess(score::cpp::stop_token s // - Terminating: A termination is in progress (allowed) if (!setState(score::mw::lifecycle::ProcessState::kIdle)) { - LM_LOG_WARN() << "Starting" << logId() << "failed: termination in progress"; + LM_LOG_WARN() << logId() << "starting failed: termination in progress"; error = ComponentError::kErrorBeforeReady; break; } @@ -308,7 +312,7 @@ IComponent::RequestResult ProcessInfoNode::startProcess(score::cpp::stop_token s sync_.reset(); } const std::chrono::time_point finished_time = std::chrono::steady_clock::now(); - LM_LOG_DEBUG() << "startProcess for" << logId() << "done, took" + LM_LOG_DEBUG() << logId() << "startProcess done, took" << std::chrono::round(finished_time - initial_time); if (error.has_value()) @@ -360,11 +364,9 @@ void ProcessInfoNode::setupControlClientChannel() std::atomic_store(&control_client_channel_, ControlClientChannel::getControlClientChannel(sync_)); } -std::string ProcessInfoNode::logId() const +ProcessLogId ProcessInfoNode::logId() const { - std::ostringstream oss; - oss << "Name: " << identifier_ << ", PID: " << pid_; - return oss.str(); + return {identifier_, pid_}; } score::cpp::expected_blank ProcessInfoNode::handleProcessStillStarting( @@ -407,7 +409,7 @@ score::cpp::expected_blank ProcessInfoNode::handlePr if (wait_res != osal::OsalReturnType::kSuccess) { - LM_LOG_ERROR() << "Error waiting for file for" << logId(); + LM_LOG_ERROR() << logId() << "error waiting for file"; } return (wait_res == osal::OsalReturnType::kSuccess) && (exit_code_ == 0); @@ -426,7 +428,7 @@ score::cpp::expected_blank ProcessInfoNode::handlePr return score::cpp::make_unexpected(ComponentError::kErrorBeforeReady); } - LM_LOG_WARN() << "Got kRunning timeout for" << logId(); + LM_LOG_WARN() << logId() << "got kRunning timeout"; terminateProcess(stop_token); return score::cpp::make_unexpected(ComponentError::kActivationTimedOut); } @@ -457,7 +459,7 @@ ProcessInfoNode::handleProcessStarted(const score::cpp::stop_token& stop_token) return handleProcessAlreadyTerminated(); default: // Error case when pn == -1 // really bad fatal error, should not happen, treat as a failure to set the state & kill the process - LM_LOG_ERROR() << "Could not add" << logId() << "to process map!"; + LM_LOG_ERROR() << logId() << "could not add to process map!"; terminateProcess(stop_token); return score::cpp::make_unexpected(ComponentError::kErrorBeforeReady); } @@ -467,37 +469,37 @@ void ProcessInfoNode::handleProcessRunning() { if (!isReporting()) { - LM_LOG_DEBUG() << "Considered kRunning for non-reporting" << logId(); + LM_LOG_DEBUG() << logId() << "considered kRunning (non-reporting)"; } else { - LM_LOG_DEBUG() << "Got kRunning for" << logId(); + LM_LOG_DEBUG() << logId() << "got kRunning"; } } void ProcessInfoNode::terminateProcess(const score::cpp::stop_token& stop_token) { - LM_LOG_DEBUG() << "Terminating" << logId(); + LM_LOG_DEBUG() << logId() << "terminating"; if (setState(score::mw::lifecycle::ProcessState::kTerminating)) { handleTerminationProcess(stop_token); } - LM_LOG_DEBUG() << "terminateProcess for" << logId() << "done"; + LM_LOG_DEBUG() << logId() << "terminateProcess done"; } void ProcessInfoNode::handleTerminationProcess(const score::cpp::stop_token& stop_token) { static_cast(terminator_.init(0U, false)); has_semaphore_.store(true); - LM_LOG_DEBUG() << "Requesting termination of" << logId(); + LM_LOG_DEBUG() << logId() << "requesting termination"; // handle request termination if ((process_handling_.process_interface_->requestTermination(pid_) == osal::OsalReturnType::kFail) || (terminator_.timedWait(std::chrono::milliseconds(config_.deployment_config.shutdown_timeout_ms)) == osal::OsalReturnType::kSuccess)) { - LM_LOG_DEBUG() << "Queuing jobs after regular termination of" << logId(); + LM_LOG_DEBUG() << logId() << "queuing jobs after regular termination"; } else { @@ -585,3 +587,17 @@ ControlClientChannelP ProcessInfoNode::getControlClientChannel() const } } // namespace score::mw::lifecycle::internal + +#ifdef LC_LOG_SCORE_MW_LOG + +namespace score::mw::lifecycle::internal +{ + +score::mw::log::LogStream& operator<<(score::mw::log::LogStream& stream, const ProcessLogId& id) +{ + return stream << "Name: " << id.identifier << ", PID: " << id.pid; +} + +} // namespace score::mw::lifecycle::internal + +#endif // LC_LOG_SCORE_MW_LOG diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.hpp b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.hpp index 8eebb555d..37fddd56e 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.hpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.hpp @@ -25,11 +25,23 @@ #include #include #include -#include +#include namespace score::mw::lifecycle::internal { +/// @brief Lightweight, allocation-free formatter for a process's standardized log identity. +/// @details Streams as "Name: , PID: ". Held by value (both members are trivially +/// copyable) so it can be passed straight to a log stream without any heap allocation. +struct ProcessLogId +{ + IdentifierHash identifier; + osal::ProcessID pid; +}; + +/// @brief Streams a ProcessLogId as "Name: , PID: ". +std::ostream& operator<<(std::ostream& os, const ProcessLogId& id); + /// @brief Represents both a process and a component in the graph. /// @details A ProcessInfoNode is a node in the dependency graph that represents an OS process and its associated /// component. It manages the lifecycle of the process, including activation, deactivation, and state reporting. The @@ -174,8 +186,8 @@ class ProcessInfoNode final : public IComponent /// @brief Creates the ControlClientChannel from the process's IPC comms handle. void setupControlClientChannel(); - /// @brief Returns a standardized identity string for logging, e.g. "Name: my_component, PID: 1234". - [[nodiscard]] std::string logId() const; + /// @brief Returns a standardized identity for logging, e.g. "Name: my_component, PID: 1234". Allocation-free. + [[nodiscard]] ProcessLogId logId() const; /// @brief semaphore used to check termination with timeout osal::Semaphore terminator_{}; @@ -226,4 +238,17 @@ class ProcessInfoNode final : public IComponent } // namespace score::mw::lifecycle::internal +#ifdef LC_LOG_SCORE_MW_LOG +#include "score/mw/log/logger.h" + +namespace score::mw::lifecycle::internal +{ + +/// @brief Streams a ProcessLogId as "Name: , PID: ". +score::mw::log::LogStream& operator<<(score::mw::log::LogStream& stream, const ProcessLogId& id); + +} // namespace score::mw::lifecycle::internal + +#endif // LC_LOG_SCORE_MW_LOG + #endif From 15a7d42eee5385481c2b43761a47d331aa67a9d3 Mon Sep 17 00:00:00 2001 From: shegazyy Date: Tue, 15 Sep 2026 18:21:21 +0300 Subject: [PATCH 3/3] Address review: unify ProcessLogId stream formatting Share the "Name:, PID:" formatting between the std::ostream and score::mw::log::LogStream overloads via one templated helper instead of duplicating the same stream expression in each, and drop the manual spaces after the labels since LogStream already inserts a whitespace between successive stream operations. Co-Authored-By: Claude Sonnet 5 --- .../details/process_info_node.cpp | 17 +++++++++++++++-- .../details/process_info_node.hpp | 7 ++++--- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp index 718ef511f..923a90f7d 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.cpp @@ -24,9 +24,22 @@ namespace score::mw::lifecycle::internal { +namespace +{ +// Shared by both the std::ostream and score::mw::log::LogStream overloads below so the +// formatting only lives in one place. mw::log::LogStream automatically inserts a whitespace +// between successive stream operations, so the literals below intentionally omit it; the +// plain std::ostream fallback renders slightly more tightly as a result. +template +StreamT& streamProcessLogId(StreamT& stream, const ProcessLogId& id) +{ + return stream << "Name:" << id.identifier << ", PID:" << id.pid; +} +} // namespace + std::ostream& operator<<(std::ostream& os, const ProcessLogId& id) { - return os << "Name: " << id.identifier << ", PID: " << id.pid; + return streamProcessLogId(os, id); } ProcessInfoNode::ProcessInfoNode(configuration::ComponentConfig&& config, ProcessHandling process_handling) @@ -595,7 +608,7 @@ namespace score::mw::lifecycle::internal score::mw::log::LogStream& operator<<(score::mw::log::LogStream& stream, const ProcessLogId& id) { - return stream << "Name: " << id.identifier << ", PID: " << id.pid; + return streamProcessLogId(stream, id); } } // namespace score::mw::lifecycle::internal diff --git a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.hpp b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.hpp index 37fddd56e..fc7267f06 100644 --- a/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.hpp +++ b/score/launch_manager/src/daemon/src/process_group_manager/details/process_info_node.hpp @@ -31,15 +31,16 @@ namespace score::mw::lifecycle::internal { /// @brief Lightweight, allocation-free formatter for a process's standardized log identity. -/// @details Streams as "Name: , PID: ". Held by value (both members are trivially -/// copyable) so it can be passed straight to a log stream without any heap allocation. +/// @details Streams as "Name:, PID:" (score::mw::log::LogStream inserts the +/// separating whitespace itself). Held by value (both members are trivially copyable) so it +/// can be passed straight to a log stream without any heap allocation. struct ProcessLogId { IdentifierHash identifier; osal::ProcessID pid; }; -/// @brief Streams a ProcessLogId as "Name: , PID: ". +/// @brief Streams a ProcessLogId as "Name:, PID:". std::ostream& operator<<(std::ostream& os, const ProcessLogId& id); /// @brief Represents both a process and a component in the graph.