From bc42fd45c371d903a1e2b9d9ae0e67135e5b82ee Mon Sep 17 00:00:00 2001 From: SystemsPurge Date: Wed, 16 Apr 2025 12:41:34 +0200 Subject: [PATCH 1/4] Add metrics path API handler Signed-off-by: SystemsPurge --- lib/api/CMakeLists.txt | 1 + lib/api/requests/metrics.cpp | 74 ++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 lib/api/requests/metrics.cpp diff --git a/lib/api/CMakeLists.txt b/lib/api/CMakeLists.txt index b52e3eee1..70974bdeb 100644 --- a/lib/api/CMakeLists.txt +++ b/lib/api/CMakeLists.txt @@ -26,6 +26,7 @@ set(API_SRC requests/node_stats.cpp requests/node_stats_reset.cpp requests/node_file.cpp + requests/metrics.cpp requests/paths.cpp requests/path_info.cpp requests/path_action.cpp diff --git a/lib/api/requests/metrics.cpp b/lib/api/requests/metrics.cpp new file mode 100644 index 000000000..b44994639 --- /dev/null +++ b/lib/api/requests/metrics.cpp @@ -0,0 +1,74 @@ +/* The "nodes" API ressource. + * + * Author: Steffen Vogel + * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace villas { +namespace node { +namespace api { + +class MetricsRequest : public Request { +private: +std::unordered_map metrics_subset = { + {Stats::Metric::SMPS_SKIPPED,"skipped"}, + {Stats::Metric::OWD,"owd"}, + {Stats::Metric::AGE,"age"}, + {Stats::Metric::SIGNAL_COUNT,"signalcnt"}, + {Stats::Metric::RTP_PKTS_LOST,"rtp_pkts_lost"} +}; + +public: + using Request::Request; + + virtual Response *execute() { + if (method != Session::Method::GET) + throw InvalidMethod(this); + + if (body != nullptr) + throw BadRequest("Nodes endpoint does not accept any body data"); + + + std::string text_res = ""; + NodeList node_list = session->getSuperNode()->getNodes(); + for(Node* node: node_list){ + auto stats = node->getStats(); + if(!stats) + continue; + std::string node_name = node->getNameShort(); + for(auto& metric:metrics_subset){ + Hist histogram = stats->getHistogram(metric.first); + std::string t =std::to_string( + std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch() + ).count() + ); + text_res+=metric.second+" {node=\""+node_name+"\" acc=\"last\"} "+std::to_string(histogram.getLast())+" "+t+"\n"; + text_res+=metric.second+" {node=\""+node_name+"\" acc=\"total\"} "+std::to_string(histogram.getTotal())+" "+t+"\n"; + } + } + + return new Response(session,HTTP_STATUS_OK, "text/plain; charset=UTF-8", Buffer(text_res.c_str(),text_res.size())); + } +}; + +// Register API request +static char n[] = "metrics"; +static char r[] = "/metrics"; +static char d[] = "Get stats of all nodes in desired format"; +static RequestPlugin p; + +} // namespace api +} // namespace node +} // namespace villas From c8748e1c4945dfbb3bf763653ceebf0fe400b3fe Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 24 Apr 2025 08:12:38 +0200 Subject: [PATCH 2/4] fix(api): Fix file header info of metrics endpoint Signed-off-by: Steffen Vogel --- lib/api/requests/metrics.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/api/requests/metrics.cpp b/lib/api/requests/metrics.cpp index b44994639..e3e893444 100644 --- a/lib/api/requests/metrics.cpp +++ b/lib/api/requests/metrics.cpp @@ -1,7 +1,7 @@ -/* The "nodes" API ressource. +/* The Prometheus metrics endpoint. * - * Author: Steffen Vogel - * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University + * Author: Youssef Nakti + * SPDX-FileCopyrightText: 2025 Institute for Automation of Complex Power Systems, RWTH Aachen University * SPDX-License-Identifier: Apache-2.0 */ @@ -66,7 +66,7 @@ std::unordered_map metrics_subset = { // Register API request static char n[] = "metrics"; static char r[] = "/metrics"; -static char d[] = "Get stats of all nodes in desired format"; +static char d[] = "Get Prometheus metrics from all nodes"; static RequestPlugin p; } // namespace api From 7d4ede4a9468fd424ef703380a8ee10d783dfd6f Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 24 Apr 2025 08:14:42 +0200 Subject: [PATCH 3/4] fix(api): Fix code-formatting Signed-off-by: Steffen Vogel --- lib/api/requests/metrics.cpp | 43 +++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/lib/api/requests/metrics.cpp b/lib/api/requests/metrics.cpp index e3e893444..66aa2575d 100644 --- a/lib/api/requests/metrics.cpp +++ b/lib/api/requests/metrics.cpp @@ -5,8 +5,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include -#include #include #include #include @@ -21,13 +21,12 @@ namespace api { class MetricsRequest : public Request { private: -std::unordered_map metrics_subset = { - {Stats::Metric::SMPS_SKIPPED,"skipped"}, - {Stats::Metric::OWD,"owd"}, - {Stats::Metric::AGE,"age"}, - {Stats::Metric::SIGNAL_COUNT,"signalcnt"}, - {Stats::Metric::RTP_PKTS_LOST,"rtp_pkts_lost"} -}; + std::unordered_map metrics_subset = { + {Stats::Metric::SMPS_SKIPPED, "skipped"}, + {Stats::Metric::OWD, "owd"}, + {Stats::Metric::AGE, "age"}, + {Stats::Metric::SIGNAL_COUNT, "signalcnt"}, + {Stats::Metric::RTP_PKTS_LOST, "rtp_pkts_lost"}}; public: using Request::Request; @@ -39,27 +38,31 @@ std::unordered_map metrics_subset = { if (body != nullptr) throw BadRequest("Nodes endpoint does not accept any body data"); - std::string text_res = ""; NodeList node_list = session->getSuperNode()->getNodes(); - for(Node* node: node_list){ + for (Node *node : node_list) { auto stats = node->getStats(); - if(!stats) + if (!stats) continue; std::string node_name = node->getNameShort(); - for(auto& metric:metrics_subset){ + for (auto &metric : metrics_subset) { Hist histogram = stats->getHistogram(metric.first); - std::string t =std::to_string( - std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch() - ).count() - ); - text_res+=metric.second+" {node=\""+node_name+"\" acc=\"last\"} "+std::to_string(histogram.getLast())+" "+t+"\n"; - text_res+=metric.second+" {node=\""+node_name+"\" acc=\"total\"} "+std::to_string(histogram.getTotal())+" "+t+"\n"; + std::string t = std::to_string( + std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count()); + + text_res += metric.second + " {node=\"" + node_name + + "\" acc=\"last\"} " + std::to_string(histogram.getLast()) + + " " + t + "\n"; + text_res += metric.second + " {node=\"" + node_name + + "\" acc=\"total\"} " + + std::to_string(histogram.getTotal()) + " " + t + "\n"; } } - return new Response(session,HTTP_STATUS_OK, "text/plain; charset=UTF-8", Buffer(text_res.c_str(),text_res.size())); + return new Response(session, HTTP_STATUS_OK, "text/plain; charset=UTF-8", + Buffer(text_res.c_str(), text_res.size())); } }; From 77e4815352f535527770a8ae6eeb5418c8f3c1ce Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 24 Apr 2025 11:04:49 +0200 Subject: [PATCH 4/4] feat(api-metrics): Add integration test Signed-off-by: Steffen Vogel --- tests/integration/api-metrics.sh | 56 ++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100755 tests/integration/api-metrics.sh diff --git a/tests/integration/api-metrics.sh b/tests/integration/api-metrics.sh new file mode 100755 index 000000000..84d673887 --- /dev/null +++ b/tests/integration/api-metrics.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash +# +# Integration test for remote API +# +# Author: Steffen Vogel +# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + +set -e + +DIR=$(mktemp -d) +pushd ${DIR} + +function finish { + popd + rm -rf ${DIR} +} +trap finish EXIT + +cat > config.json < metrics + +# Shutdown VILLASnode +kill $! + +cat metrics