tlbmc: Add shared memory support for Requests Per Second metrics
This change adds the core functionality to `TlbmcMetrics` to calculate and store Requests Per Second (RPS) for both TLBMC and gBMCWeb Redfish requests.
The key additions are:
- `UpdateMetricsRps(absl::Duration)` in `TlbmcMetrics` to calculate RPS based on request count changes over time.
- Atomic member variables to store TLBMC, gBMCWeb, and total RPS values.
- Exposure of the new RPS metrics via `ToJson()` and new getter methods.
- An update to `SharedMemoryServer` to provide access to `UpdateMetricsRps`.
This provides the necessary infrastructure in shared memory for higher-level components to trigger RPS calculation. Unit tests for the RPS calculation logic are included.
#tlbmc
#bmc-offsite
PiperOrigin-RevId: 822722354
Change-Id: I1709e8dd261a657b6ad45402dbe19ac5ca271c51
diff --git a/tlbmc/hal/shared_mem/metrics.cc b/tlbmc/hal/shared_mem/metrics.cc
index 5ccd646..3691337 100644
--- a/tlbmc/hal/shared_mem/metrics.cc
+++ b/tlbmc/hal/shared_mem/metrics.cc
@@ -68,6 +68,31 @@
}
}
+void TlbmcMetrics::UpdateMetricsRps(absl::Duration time_delta) {
+ if (time_delta > absl::ZeroDuration()) {
+ MetricsIntegerType current_tlbmc_request_count =
+ total_tlbmc_request_count_.load();
+ MetricsIntegerType current_bmcweb_request_count =
+ total_gbmcweb_request_count_.load();
+
+ MetricsIntegerType tlbmc_rate = static_cast<MetricsIntegerType>(
+ (static_cast<double>(current_tlbmc_request_count -
+ prev_tlbmc_request_count_.load())) /
+ absl::ToDoubleSeconds(time_delta));
+ MetricsIntegerType bmcweb_rate = static_cast<MetricsIntegerType>(
+ (static_cast<double>(current_bmcweb_request_count -
+ prev_bmcweb_request_count_.load())) /
+ absl::ToDoubleSeconds(time_delta));
+
+ tlbmc_requests_per_second_.store(tlbmc_rate);
+ bmcweb_requests_per_second_.store(bmcweb_rate);
+ total_requests_per_second_.store(tlbmc_rate + bmcweb_rate);
+
+ prev_tlbmc_request_count_.store(current_tlbmc_request_count);
+ prev_bmcweb_request_count_.store(current_bmcweb_request_count);
+ }
+}
+
nlohmann::json TlbmcMetrics::ToJson() const {
return ToJson(kTopLatencyResourcesCount);
}
@@ -80,6 +105,9 @@
nlohmann::json json;
json["TotalTlbmcRequestCount"] = total_tlbmc_request_count_.load();
json["TotalGbmcwebRequestCount"] = total_gbmcweb_request_count_.load();
+ json["TlbmcRequestsPerSecond"] = tlbmc_requests_per_second_.load();
+ json["BmcwebRequestsPerSecond"] = bmcweb_requests_per_second_.load();
+ json["TotalRequestsPerSecond"] = total_requests_per_second_.load();
// Response status code count.
nlohmann::json::array_t response_status_code_count_json;
for (int code : kSupportedStatusCodes) {
diff --git a/tlbmc/hal/shared_mem/metrics.h b/tlbmc/hal/shared_mem/metrics.h
index 1df50b6..10a6a5b 100644
--- a/tlbmc/hal/shared_mem/metrics.h
+++ b/tlbmc/hal/shared_mem/metrics.h
@@ -5,6 +5,8 @@
#include <array>
#include <atomic>
+#include <chrono> // NOLINT
+#include <cmath>
#include <cstddef>
#include <cstdint>
#include <string_view>
@@ -50,6 +52,8 @@
void UpdateMetricsRequestCount(bool is_tlbmc_request);
void UpdateMetricsResponse(absl::Duration response_time, int status_code,
std::string_view resource_url);
+ // Calculates the Requests Per Second of TLBMC and gBMCWeb Redfish requests.
+ void UpdateMetricsRps(absl::Duration time_delta);
// Dumps to a JSON used for metrics collection. Contains the top
// `kTopLatencyResourcesCount` resources with the highest average latency.
// This call is expensive. Please call it only periodically, e.g., every
@@ -60,6 +64,23 @@
nlohmann::json ToJson(int top_latency_resources_count) const;
// Dumps to a JSON used for debugging.
nlohmann::json ToDebugJson() const;
+
+ MetricsIntegerType GetTlbmcRequestCount() const {
+ return total_tlbmc_request_count_.load();
+ }
+
+ MetricsIntegerType GetGbmcwebRequestCount() const {
+ return total_gbmcweb_request_count_.load();
+ }
+ MetricsIntegerType GetTlbmcRps() const {
+ return tlbmc_requests_per_second_.load();
+ }
+ MetricsIntegerType GetBmcwebRps() const {
+ return bmcweb_requests_per_second_.load();
+ }
+ MetricsIntegerType GetTotalRps() const {
+ return total_requests_per_second_.load();
+ }
// copybara:strip_end
private:
@@ -79,6 +100,12 @@
// TODO(nanzhou): handles overflow.
std::atomic<MetricsIntegerType>
response_total_latency_ms_per_resource_[kResourceCount] = {0};
+
+ std::atomic<MetricsIntegerType> tlbmc_requests_per_second_ = 0;
+ std::atomic<MetricsIntegerType> bmcweb_requests_per_second_ = 0;
+ std::atomic<MetricsIntegerType> total_requests_per_second_ = 0;
+ std::atomic<MetricsIntegerType> prev_tlbmc_request_count_ = 0;
+ std::atomic<MetricsIntegerType> prev_bmcweb_request_count_ = 0;
};
} // namespace milotic_tlbmc
diff --git a/tlbmc/hal/shared_mem/server.cc b/tlbmc/hal/shared_mem/server.cc
index bf0acd5..1ca9ea5 100644
--- a/tlbmc/hal/shared_mem/server.cc
+++ b/tlbmc/hal/shared_mem/server.cc
@@ -140,6 +140,13 @@
}
metrics_->UpdateMetricsResponse(response_time, status_code, resource_url);
}
+
+void SharedMemoryServer::UpdateMetricsRps(absl::Duration time_delta) {
+ if (metrics_ == nullptr) {
+ return;
+ }
+ metrics_->UpdateMetricsRps(time_delta);
+}
// copybara:strip_end
} // namespace milotic_tlbmc
diff --git a/tlbmc/hal/shared_mem/server.h b/tlbmc/hal/shared_mem/server.h
index 6cca6cb..853f1ad 100644
--- a/tlbmc/hal/shared_mem/server.h
+++ b/tlbmc/hal/shared_mem/server.h
@@ -30,6 +30,7 @@
virtual void UpdateMetricsResponse(absl::Duration response_time,
int status_code,
std::string_view resource_url) = 0;
+ virtual void UpdateMetricsRps(absl::Duration time_delta) = 0;
// copybara:strip_end
virtual const TlbmcMetrics* GetMetrics() const = 0;
};
@@ -73,6 +74,7 @@
void UpdateMetricsRequestCount(bool is_tlbmc_request) override;
void UpdateMetricsResponse(absl::Duration response_time, int status_code,
std::string_view resource_url) override;
+ void UpdateMetricsRps(absl::Duration time_delta) override;
// copybara:strip_end
SharedMemoryServer(Token token, const std::string& initialized_file_path,