This repository has been archived by the owner on Jun 10, 2021. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Measure linux cpu active percentage (#11)
* Add linux cpu measurement node * Add API improvements * Split linux cpu measurement header and implementation * Test improvements * Cleanups * Add main used for manual testing * Split cpu_data header and implementation * Add missing implementation file * Address review comments * Address review comments * Rename files to reflect class name
- Loading branch information
Showing
14 changed files
with
683 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
97 changes: 97 additions & 0 deletions
97
system_metrics_collector/src/system_metrics_collector/linux_cpu_measurement_node.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
#include <chrono> | ||
#include <string> | ||
|
||
#include "linux_cpu_measurement_node.hpp" | ||
|
||
namespace | ||
{ | ||
constexpr const char PROC_STAT_FILE[] = "/proc/stat"; | ||
constexpr const char CPU_LABEL[] = "cpu"; | ||
constexpr const size_t CPU_LABEL_LENGTH = 3; | ||
} // namespace | ||
|
||
ProcCpuData processLine(const std::string & stat_cpu_line) | ||
{ | ||
ProcCpuData parsed_data; | ||
|
||
if (!stat_cpu_line.empty()) { | ||
if (!stat_cpu_line.compare(0, CPU_LABEL_LENGTH, CPU_LABEL)) { | ||
std::istringstream ss(stat_cpu_line); | ||
|
||
if (!ss.good()) { | ||
return ProcCpuData(); | ||
} | ||
ss >> parsed_data.cpu_label; | ||
|
||
for (int i = 0; i < static_cast<int>(ProcCpuStates::kNumProcCpuStates); ++i) { | ||
if (!ss.good()) { | ||
return ProcCpuData(); | ||
} | ||
ss >> parsed_data.times[i]; | ||
} | ||
|
||
return parsed_data; | ||
} | ||
} | ||
return parsed_data; | ||
} | ||
|
||
double computeCpuActivePercentage( | ||
const ProcCpuData & measurement1, | ||
const ProcCpuData & measurement2) | ||
{ | ||
if (measurement1.isMeasurementEmpty() || measurement2.isMeasurementEmpty()) { | ||
return std::nan(""); | ||
} | ||
|
||
const double active_time = measurement2.getActiveTime() - measurement1.getActiveTime(); | ||
const double total_time = (measurement2.getIdleTime() + measurement2.getActiveTime()) - | ||
(measurement1.getIdleTime() + measurement2.getActiveTime()); | ||
|
||
return 100.0 * active_time / total_time; | ||
} | ||
|
||
LinuxCpuMeasurementNode::LinuxCpuMeasurementNode( | ||
const std::string & name, | ||
const std::chrono::milliseconds measurement_period, | ||
const std::string & topic, | ||
const std::chrono::milliseconds & publish_period) | ||
: PeriodicMeasurementNode(name, measurement_period, topic, publish_period), | ||
last_measurement_() | ||
{} | ||
|
||
double LinuxCpuMeasurementNode::periodicMeasurement() | ||
{ | ||
ProcCpuData current_measurement = makeSingleMeasurement(); | ||
|
||
const double cpu_percentage = computeCpuActivePercentage( | ||
last_measurement_, | ||
current_measurement); | ||
|
||
last_measurement_ = current_measurement; | ||
|
||
return cpu_percentage; | ||
} | ||
|
||
ProcCpuData LinuxCpuMeasurementNode::makeSingleMeasurement() | ||
{ | ||
std::ifstream stat_file(PROC_STAT_FILE); | ||
std::string line; | ||
std::getline(stat_file, line); | ||
|
||
return stat_file.good() ? processLine(line) : ProcCpuData(); | ||
} |
86 changes: 86 additions & 0 deletions
86
system_metrics_collector/src/system_metrics_collector/linux_cpu_measurement_node.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
#ifndef SYSTEM_METRICS_COLLECTOR__LINUX_CPU_MEASUREMENT_NODE_HPP_ | ||
#define SYSTEM_METRICS_COLLECTOR__LINUX_CPU_MEASUREMENT_NODE_HPP_ | ||
|
||
#include <fstream> | ||
#include <iostream> | ||
#include <sstream> | ||
#include <string> | ||
|
||
#include "../../src/system_metrics_collector/periodic_measurement_node.hpp" | ||
#include "../../src/system_metrics_collector/proc_cpu_data.hpp" | ||
|
||
/** | ||
* Parse a line read from /proc/stat | ||
* | ||
* @param stat_cpu_line a line from /proc/stat | ||
* @return ProcCpuData struct populated if parsed, otherwise empty | ||
*/ | ||
ProcCpuData processLine(const std::string & stat_cpu_line); | ||
|
||
/** | ||
* Compute the percentage of CPU active. | ||
* | ||
* @param measurement1 the first measurement | ||
* @param measurement2 the second measurement (made after the first) | ||
* @return percentage of CPU active | ||
*/ | ||
double computeCpuActivePercentage( | ||
const ProcCpuData & measurement1, | ||
const ProcCpuData & measurement2); | ||
|
||
/** | ||
* Node that periodically calculates the % of active CPU by | ||
* reading /proc/stat. | ||
*/ | ||
class LinuxCpuMeasurementNode : public PeriodicMeasurementNode | ||
{ | ||
public: | ||
/** | ||
* | ||
* @param name | ||
* @param measurement_period | ||
* @param topic | ||
*/ | ||
LinuxCpuMeasurementNode( | ||
const std::string & name, | ||
const std::chrono::milliseconds measurement_period, | ||
const std::string & topic, | ||
const std::chrono::milliseconds & publish_period = | ||
PeriodicMeasurementNode::DEFAULT_PUBLISH_WINDOW); | ||
|
||
virtual ~LinuxCpuMeasurementNode() = default; | ||
|
||
protected: | ||
/** | ||
* Perform a periodic measurement calculating the percentage of CPU active. | ||
* | ||
* @return percentage of CPU active | ||
*/ | ||
double periodicMeasurement() override; | ||
|
||
private: | ||
/** | ||
* Perform a single measurement of cpu data by reading /proc/stat. | ||
* | ||
* @return ProcCpuData the measurement made | ||
*/ | ||
virtual ProcCpuData makeSingleMeasurement(); | ||
|
||
ProcCpuData last_measurement_; | ||
}; | ||
|
||
#endif // SYSTEM_METRICS_COLLECTOR__LINUX_CPU_MEASUREMENT_NODE_HPP_ |
61 changes: 61 additions & 0 deletions
61
system_metrics_collector/src/system_metrics_collector/main.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
|
||
#include <functional> | ||
|
||
#include <chrono> | ||
#include <memory> | ||
#include <string> | ||
|
||
#include "rclcpp/rclcpp.hpp" | ||
|
||
#include "../../src/system_metrics_collector/linux_cpu_measurement_node.hpp" | ||
|
||
/** | ||
* This is current a "test" main in order to manually test the measurement nodes. | ||
* | ||
* @param argc | ||
* @param argv | ||
* @return | ||
*/ | ||
int main(int argc, char ** argv) | ||
{ | ||
rclcpp::init(argc, argv); | ||
|
||
auto node = std::make_shared<LinuxCpuMeasurementNode>( | ||
"linuxCpuCollector", | ||
std::chrono::milliseconds(1000), | ||
"not_publishing_yet", | ||
std::chrono::milliseconds(1000 * 60)); | ||
|
||
rclcpp::executors::SingleThreadedExecutor ex; | ||
node->start(); | ||
|
||
int code = 0; | ||
auto r = rcutils_logging_set_logger_level(node->get_name(), RCUTILS_LOG_SEVERITY_DEBUG); | ||
|
||
if (r != 0) { | ||
std::cout << "Unabled to set debug logging!" << std::endl; | ||
code = 1; | ||
} else { | ||
ex.add_node(node); | ||
ex.spin(); | ||
} | ||
|
||
|
||
rclcpp::shutdown(); | ||
node->stop(); | ||
return code; | ||
} |
Oops, something went wrong.