LCOV - code coverage report
Current view: top level - source/common/upstream - host_utility.cc (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 28 175 16.0 %
Date: 2024-01-05 06:35:25 Functions: 4 7 57.1 %

          Line data    Source code
       1             : #include "source/common/upstream/host_utility.h"
       2             : 
       3             : #include <string>
       4             : 
       5             : #include "source/common/config/well_known_names.h"
       6             : #include "source/common/runtime/runtime_features.h"
       7             : 
       8             : namespace Envoy {
       9             : namespace Upstream {
      10             : namespace {
      11             : 
      12           0 : void setHealthFlag(Upstream::Host::HealthFlag flag, const Host& host, std::string& health_status) {
      13           0 :   switch (flag) {
      14           0 :   case Host::HealthFlag::FAILED_ACTIVE_HC: {
      15           0 :     if (host.healthFlagGet(Host::HealthFlag::FAILED_ACTIVE_HC)) {
      16           0 :       health_status += "/failed_active_hc";
      17           0 :     }
      18           0 :     break;
      19           0 :   }
      20             : 
      21           0 :   case Host::HealthFlag::FAILED_OUTLIER_CHECK: {
      22           0 :     if (host.healthFlagGet(Host::HealthFlag::FAILED_OUTLIER_CHECK)) {
      23           0 :       health_status += "/failed_outlier_check";
      24           0 :     }
      25           0 :     break;
      26           0 :   }
      27             : 
      28           0 :   case Host::HealthFlag::FAILED_EDS_HEALTH: {
      29           0 :     if (host.healthFlagGet(Host::HealthFlag::FAILED_EDS_HEALTH)) {
      30           0 :       health_status += "/failed_eds_health";
      31           0 :     }
      32           0 :     break;
      33           0 :   }
      34             : 
      35           0 :   case Host::HealthFlag::DEGRADED_ACTIVE_HC: {
      36           0 :     if (host.healthFlagGet(Host::HealthFlag::DEGRADED_ACTIVE_HC)) {
      37           0 :       health_status += "/degraded_active_hc";
      38           0 :     }
      39           0 :     break;
      40           0 :   }
      41             : 
      42           0 :   case Host::HealthFlag::DEGRADED_EDS_HEALTH: {
      43           0 :     if (host.healthFlagGet(Host::HealthFlag::DEGRADED_EDS_HEALTH)) {
      44           0 :       health_status += "/degraded_eds_health";
      45           0 :     }
      46           0 :     break;
      47           0 :   }
      48             : 
      49           0 :   case Host::HealthFlag::PENDING_DYNAMIC_REMOVAL: {
      50           0 :     if (host.healthFlagGet(Host::HealthFlag::PENDING_DYNAMIC_REMOVAL)) {
      51           0 :       health_status += "/pending_dynamic_removal";
      52           0 :     }
      53           0 :     break;
      54           0 :   }
      55             : 
      56           0 :   case Host::HealthFlag::PENDING_ACTIVE_HC: {
      57           0 :     if (host.healthFlagGet(Host::HealthFlag::PENDING_ACTIVE_HC)) {
      58           0 :       health_status += "/pending_active_hc";
      59           0 :     }
      60           0 :     break;
      61           0 :   }
      62             : 
      63           0 :   case Host::HealthFlag::EXCLUDED_VIA_IMMEDIATE_HC_FAIL: {
      64           0 :     if (host.healthFlagGet(Host::HealthFlag::EXCLUDED_VIA_IMMEDIATE_HC_FAIL)) {
      65           0 :       health_status += "/excluded_via_immediate_hc_fail";
      66           0 :     }
      67           0 :     break;
      68           0 :   }
      69             : 
      70           0 :   case Host::HealthFlag::ACTIVE_HC_TIMEOUT: {
      71           0 :     if (host.healthFlagGet(Host::HealthFlag::ACTIVE_HC_TIMEOUT)) {
      72           0 :       health_status += "/active_hc_timeout";
      73           0 :     }
      74           0 :     break;
      75           0 :   }
      76           0 :   }
      77           0 : }
      78             : 
      79             : } // namespace
      80             : 
      81           0 : std::string HostUtility::healthFlagsToString(const Host& host) {
      82           0 :   std::string health_status;
      83             : 
      84             :   // Invokes setHealthFlag for each health flag.
      85           0 : #define SET_HEALTH_FLAG(name, notused)                                                             \
      86           0 :   setHealthFlag(Upstream::Host::HealthFlag::name, host, health_status);
      87           0 :   HEALTH_FLAG_ENUM_VALUES(SET_HEALTH_FLAG)
      88           0 : #undef SET_HEALTH_FLAG
      89             : 
      90           0 :   if (health_status.empty()) {
      91           0 :     return "healthy";
      92           0 :   } else {
      93           0 :     return health_status;
      94           0 :   }
      95           0 : }
      96             : 
      97             : HostUtility::HostStatusSet HostUtility::createOverrideHostStatus(
      98         306 :     const envoy::config::cluster::v3::Cluster::CommonLbConfig& common_config) {
      99         306 :   HostStatusSet override_host_status;
     100             : 
     101         306 :   if (!common_config.has_override_host_status()) {
     102             :     // No override host status and [UNKNOWN, HEALTHY, DEGRADED] will be applied by default.
     103         306 :     override_host_status.set(static_cast<uint32_t>(envoy::config::core::v3::HealthStatus::UNKNOWN));
     104         306 :     override_host_status.set(static_cast<uint32_t>(envoy::config::core::v3::HealthStatus::HEALTHY));
     105         306 :     override_host_status.set(
     106         306 :         static_cast<uint32_t>(envoy::config::core::v3::HealthStatus::DEGRADED));
     107         306 :     return override_host_status;
     108         306 :   }
     109             : 
     110           0 :   for (auto single_status : common_config.override_host_status().statuses()) {
     111           0 :     switch (static_cast<envoy::config::core::v3::HealthStatus>(single_status)) {
     112           0 :       PANIC_ON_PROTO_ENUM_SENTINEL_VALUES;
     113           0 :     case envoy::config::core::v3::HealthStatus::UNKNOWN:
     114           0 :     case envoy::config::core::v3::HealthStatus::HEALTHY:
     115           0 :     case envoy::config::core::v3::HealthStatus::UNHEALTHY:
     116           0 :     case envoy::config::core::v3::HealthStatus::DRAINING:
     117           0 :     case envoy::config::core::v3::HealthStatus::TIMEOUT:
     118           0 :     case envoy::config::core::v3::HealthStatus::DEGRADED:
     119           0 :       override_host_status.set(static_cast<uint32_t>(single_status));
     120           0 :       break;
     121           0 :     }
     122           0 :   }
     123           0 :   return override_host_status;
     124           0 : }
     125             : 
     126             : HostConstSharedPtr HostUtility::selectOverrideHost(const HostMap* host_map, HostStatusSet status,
     127         251 :                                                    LoadBalancerContext* context) {
     128         251 :   if (context == nullptr) {
     129           0 :     return nullptr;
     130           0 :   }
     131             : 
     132         251 :   auto override_host = context->overrideHostToSelect();
     133         251 :   if (!override_host.has_value()) {
     134         251 :     return nullptr;
     135         251 :   }
     136             : 
     137           0 :   if (host_map == nullptr) {
     138           0 :     return nullptr;
     139           0 :   }
     140             : 
     141           0 :   auto host_iter = host_map->find(override_host.value().first);
     142             : 
     143             :   // The override host cannot be found in the host map.
     144           0 :   if (host_iter == host_map->end()) {
     145           0 :     return nullptr;
     146           0 :   }
     147             : 
     148           0 :   HostConstSharedPtr host = host_iter->second;
     149           0 :   ASSERT(host != nullptr);
     150             : 
     151           0 :   if (status[static_cast<uint32_t>(host->healthStatus())]) {
     152           0 :     return host;
     153           0 :   }
     154           0 :   return nullptr;
     155           0 : }
     156             : 
     157         251 : bool HostUtility::allowLBChooseHost(LoadBalancerContext* context) {
     158         251 :   if (context == nullptr) {
     159           0 :     return true;
     160           0 :   }
     161             : 
     162         251 :   auto override_host = context->overrideHostToSelect();
     163         251 :   if (!override_host.has_value()) {
     164         251 :     return true;
     165         251 :   }
     166             : 
     167             :   // Return opposite value to "strict" setting.
     168           0 :   return !override_host.value().second;
     169         251 : }
     170             : 
     171             : void HostUtility::forEachHostMetric(
     172             :     const ClusterManager& cluster_manager,
     173             :     const std::function<void(Stats::PrimitiveCounterSnapshot&& metric)>& counter_cb,
     174         111 :     const std::function<void(Stats::PrimitiveGaugeSnapshot&& metric)>& gauge_cb) {
     175         172 :   for (const auto& [unused_name, cluster_ref] : cluster_manager.clusters().active_clusters_) {
     176         159 :     Upstream::ClusterInfoConstSharedPtr cluster_info = cluster_ref.get().info();
     177         159 :     if (cluster_info->perEndpointStatsEnabled()) {
     178           0 :       const std::string cluster_name =
     179           0 :           Stats::Utility::sanitizeStatsName(cluster_info->observabilityName());
     180             : 
     181           0 :       const Stats::TagVector& fixed_tags = cluster_info->statsScope().store().fixedTags();
     182             : 
     183           0 :       for (auto& host_set : cluster_ref.get().prioritySet().hostSetsPerPriority()) {
     184           0 :         for (auto& host : host_set->hosts()) {
     185             : 
     186           0 :           Stats::TagVector tags;
     187           0 :           tags.reserve(fixed_tags.size() + 3);
     188           0 :           tags.insert(tags.end(), fixed_tags.begin(), fixed_tags.end());
     189           0 :           tags.emplace_back(Stats::Tag{Envoy::Config::TagNames::get().CLUSTER_NAME, cluster_name});
     190           0 :           tags.emplace_back(Stats::Tag{"envoy.endpoint_address", host->address()->asString()});
     191             : 
     192           0 :           const auto& hostname = host->hostname();
     193           0 :           if (!hostname.empty()) {
     194           0 :             tags.push_back({"envoy.endpoint_hostname", hostname});
     195           0 :           }
     196             : 
     197           0 :           auto set_metric_metadata = [&](absl::string_view metric_name,
     198           0 :                                          Stats::PrimitiveMetricMetadata& metric) {
     199           0 :             metric.setName(
     200           0 :                 absl::StrCat("cluster.", cluster_name, ".endpoint.",
     201           0 :                              Stats::Utility::sanitizeStatsName(host->address()->asStringView()),
     202           0 :                              ".", metric_name));
     203           0 :             metric.setTagExtractedName(absl::StrCat("cluster.endpoint.", metric_name));
     204           0 :             metric.setTags(tags);
     205             : 
     206             :             // Validate that all components were sanitized.
     207           0 :             ASSERT(metric.name() == Stats::Utility::sanitizeStatsName(metric.name()));
     208           0 :             ASSERT(metric.tagExtractedName() ==
     209           0 :                    Stats::Utility::sanitizeStatsName(metric.tagExtractedName()));
     210           0 :           };
     211             : 
     212           0 :           for (auto& [metric_name, primitive] : host->counters()) {
     213           0 :             Stats::PrimitiveCounterSnapshot metric(primitive.get());
     214           0 :             set_metric_metadata(metric_name, metric);
     215             : 
     216           0 :             counter_cb(std::move(metric));
     217           0 :           }
     218             : 
     219           0 :           auto gauges = host->gauges();
     220             : 
     221             :           // Add synthetic "healthy" gauge.
     222           0 :           Stats::PrimitiveGauge healthy_gauge;
     223           0 :           healthy_gauge.set((host->coarseHealth() == Host::Health::Healthy) ? 1 : 0);
     224           0 :           gauges.emplace_back(absl::string_view("healthy"), healthy_gauge);
     225             : 
     226           0 :           for (auto& [metric_name, primitive] : gauges) {
     227           0 :             Stats::PrimitiveGaugeSnapshot metric(primitive.get());
     228           0 :             set_metric_metadata(metric_name, metric);
     229           0 :             gauge_cb(std::move(metric));
     230           0 :           }
     231           0 :         }
     232           0 :       }
     233           0 :     }
     234         159 :   }
     235         111 : }
     236             : 
     237             : } // namespace Upstream
     238             : } // namespace Envoy

Generated by: LCOV version 1.15