blob: 61d863dce5e32c119540146f940e60b3600997f0 [file] [log] [blame]
#include "tlbmc/hal/shared_mem/metrics.h"
#include <sys/stat.h>
#include <algorithm>
#include <atomic>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <iterator>
#include <limits>
#include <string>
#include <string_view>
#include <utility>
#include "absl/container/btree_set.h"
#include "absl/strings/substitute.h"
#include "absl/time/time.h"
#include "nlohmann/json.hpp"
#include "pattern_to_entity_array.h"
#include "bmcweb_authorizer_singleton.h"
namespace milotic_tlbmc {
using ::milotic::authz::BmcWebAuthorizerSingleton;
using ::milotic::authz::pattern_entity_pair_array;
void TlbmcMetrics::UpdateMetricsRequestCount(bool is_tlbmc_request) {
if (is_tlbmc_request) {
total_tlbmc_request_count_.fetch_add(1, std::memory_order_relaxed);
} else {
total_gbmcweb_request_count_.fetch_add(1, std::memory_order_relaxed);
}
}
void TlbmcMetrics::UpdateMetricsResponse(absl::Duration response_time,
int status_code,
std::string_view resource_url) {
// Update response status code count.
bool supported_status_code = std::binary_search(
kSupportedStatusCodes.begin(), kSupportedStatusCodes.end(), status_code);
if (supported_status_code) {
response_status_code_count_[status_code].fetch_add(
1, std::memory_order_relaxed);
} else {
response_status_code_count_[kMaxResponseStatusCode].fetch_add(
1, std::memory_order_relaxed);
}
// Update response time histogram.
int64_t bucket_index = response_time / kResponseTimeHistogramBucketTime;
if (bucket_index >= kResponseTimeHistogramBucketCount) {
bucket_index = 19;
}
response_time_histogram_[bucket_index].fetch_add(1,
std::memory_order_relaxed);
size_t index =
BmcWebAuthorizerSingleton::GetInstance().GetNodeIndexInPatternArray(
resource_url);
if (index != std::numeric_limits<std::size_t>::max()) {
MetricsIntegerType response_time_ms =
static_cast<MetricsIntegerType>(response_time / absl::Milliseconds(1));
response_total_latency_ms_per_resource_[index].fetch_add(
response_time_ms, std::memory_order_relaxed);
total_response_count_per_resource_[index].fetch_add(
1, std::memory_order_relaxed);
}
}
nlohmann::json TlbmcMetrics::ToJson() const {
nlohmann::json json;
json["TotalTlbmcRequestCount"] = total_tlbmc_request_count_.load();
json["TotalGbmcwebRequestCount"] = total_gbmcweb_request_count_.load();
// Response status code count.
nlohmann::json::array_t response_status_code_count;
for (int code : kSupportedStatusCodes) {
response_status_code_count.push_back(
{std::to_string(code), response_status_code_count_[code].load()});
}
response_status_code_count.push_back(
{std::to_string(kMaxResponseStatusCode),
response_status_code_count_[kMaxResponseStatusCode].load()});
json["ResponseStatusCodeCount"] = response_status_code_count;
// Response time histogram.
nlohmann::json::array_t response_time_histogram;
for (int i = 0; i < kResponseTimeHistogramBucketCount; ++i) {
std::string bucket_name;
if (i != kResponseTimeHistogramBucketCount - 1) {
bucket_name = absl::Substitute("$0ms-$1ms", i * 50, (i + 1) * 50 - 1);
} else {
bucket_name = absl::Substitute("$0ms-inf", i * 50);
}
response_time_histogram.push_back(
{bucket_name, response_time_histogram_[i].load()});
}
json["ResponseTimeHistogram"] = response_time_histogram;
// Top latency resources.
absl::btree_set<std::pair<float, int>, std::greater<>> top_latency_resources;
for (int i = 0; i < kResourceCount; ++i) {
MetricsIntegerType total_latency_ms =
response_total_latency_ms_per_resource_[i].load();
MetricsIntegerType total_response_count =
total_response_count_per_resource_[i].load();
if (total_response_count > 0) {
top_latency_resources.insert(
{static_cast<float>(total_latency_ms) /
static_cast<float>(total_response_count),
i});
if (top_latency_resources.size() > kTopLatencyResourcesCount) {
top_latency_resources.erase(std::prev(top_latency_resources.end()));
}
}
}
nlohmann::json::array_t top_latency_resources_json;
for (const auto& [average_latency_ms, index] : top_latency_resources) {
top_latency_resources_json.push_back(
{std::string(pattern_entity_pair_array[index].first),
average_latency_ms});
}
json["TopLatencyResources"] = top_latency_resources_json;
return json;
}
} // namespace milotic_tlbmc