Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[POC][DO NOT SUBMIT] Compile-time check for label size mismatch in the Metrics API #36403

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 9 additions & 9 deletions src/core/ext/xds/xds_client_grpc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -93,26 +93,26 @@ constexpr absl::string_view kMetricLabelXdsResourceType =
"grpc.xds.resource_type";
constexpr absl::string_view kMetricLabelXdsCacheState = "grpc.xds.cache_state";

std::array<absl::string_view, 3> kLabelKeys3 = {
kMetricLabelTarget, kMetricLabelXdsServer, kMetricLabelXdsResourceType};
std::array<absl::string_view, 3> kLabelKeys2 = {kMetricLabelTarget,
kMetricLabelXdsServer};
std::array<absl::string_view, 0> kEmptyOptionalLabelKeys = {};

const auto kMetricResourceUpdatesValid =
GlobalInstrumentsRegistry::RegisterUInt64Counter(
"grpc.xds_client.resource_updates_valid",
"EXPERIMENTAL. A counter of resources received that were considered "
"valid. The counter will be incremented even for resources that "
"have not changed.",
"{resource}",
{kMetricLabelTarget, kMetricLabelXdsServer,
kMetricLabelXdsResourceType},
{}, false);
"{resource}", kLabelKeys3, kEmptyOptionalLabelKeys, false);

const auto kMetricResourceUpdatesInvalid =
GlobalInstrumentsRegistry::RegisterUInt64Counter(
"grpc.xds_client.resource_updates_invalid",
"EXPERIMENTAL. A counter of resources received that were considered "
"invalid.",
"{resource}",
{kMetricLabelTarget, kMetricLabelXdsServer,
kMetricLabelXdsResourceType},
{}, false);
"{resource}", kLabelKeys3, kEmptyOptionalLabelKeys, false);

const auto kMetricServerFailure =
GlobalInstrumentsRegistry::RegisterUInt64Counter(
Expand All @@ -121,7 +121,7 @@ const auto kMetricServerFailure =
"unhealthy. A server goes unhealthy when we have a connectivity "
"failure or when the ADS stream fails without seeing a response "
"message, as per gRFC A57.",
"{failure}", {kMetricLabelTarget, kMetricLabelXdsServer}, {}, false);
"{failure}", kLabelKeys2, kEmptyOptionalLabelKeys, false);

const auto kMetricConnected =
GlobalInstrumentsRegistry::RegisterCallbackInt64Gauge(
Expand Down
99 changes: 88 additions & 11 deletions src/core/lib/channel/metrics.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,16 @@ GlobalInstrumentsRegistry::GetInstrumentList() {
return *instruments;
}

GlobalInstrumentsRegistry::GlobalUInt64CounterHandle
GlobalInstrumentsRegistry::RegisterUInt64Counter(
// 1 0
// 3 0
// 2 0
// 4 0
// 1 1

GlobalInstrumentsRegistry::InstrumentID
GlobalInstrumentsRegistry::RegisterInstrument(
GlobalInstrumentsRegistry::ValueType value_type,
GlobalInstrumentsRegistry::InstrumentType instrument_type,
absl::string_view name, absl::string_view description,
absl::string_view unit, absl::Span<const absl::string_view> label_keys,
absl::Span<const absl::string_view> optional_label_keys,
Expand All @@ -45,11 +53,11 @@ GlobalInstrumentsRegistry::RegisterUInt64Counter(
absl::StrFormat("Metric name %s has already been registered.", name));
}
}
uint32_t index = instruments.size();
InstrumentID index = instruments.size();
GPR_ASSERT(index < std::numeric_limits<uint32_t>::max());
GlobalInstrumentDescriptor descriptor;
descriptor.value_type = ValueType::kUInt64;
descriptor.instrument_type = InstrumentType::kCounter;
descriptor.value_type = value_type;
descriptor.instrument_type = instrument_type;
descriptor.index = index;
descriptor.enable_by_default = enable_by_default;
descriptor.name = name;
Expand All @@ -59,16 +67,85 @@ GlobalInstrumentsRegistry::RegisterUInt64Counter(
descriptor.optional_label_keys = {optional_label_keys.begin(),
optional_label_keys.end()};
instruments.push_back(std::move(descriptor));
GlobalUInt64CounterHandle handle;
handle.index = index;
return index;
}

template <>
GlobalInstrumentsRegistry::TemplatizedGlobalUInt64CounterHandle<1, 0>
GlobalInstrumentsRegistry::RegisterUInt64Counter<1, 0>(
absl::string_view name, absl::string_view description,
absl::string_view unit, std::array<absl::string_view, 1> label_keys,
std::array<absl::string_view, 0> optional_label_keys,
bool enable_by_default) {
TemplatizedGlobalUInt64CounterHandle<1, 0> handle;
handle.index = RegisterInstrument(
ValueType::kUInt64, InstrumentType::kCounter, name, description, unit,
label_keys, optional_label_keys, enable_by_default);
return handle;
}

template <>
GlobalInstrumentsRegistry::TemplatizedGlobalUInt64CounterHandle<3, 0>
GlobalInstrumentsRegistry::RegisterUInt64Counter<3, 0>(
absl::string_view name, absl::string_view description,
absl::string_view unit, std::array<absl::string_view, 3> label_keys,
std::array<absl::string_view, 0> optional_label_keys,
bool enable_by_default) {
TemplatizedGlobalUInt64CounterHandle<3, 0> handle;
handle.index = RegisterInstrument(
ValueType::kUInt64, InstrumentType::kCounter, name, description, unit,
label_keys, optional_label_keys, enable_by_default);
return handle;
}

GlobalInstrumentsRegistry::GlobalDoubleCounterHandle
template <>
GlobalInstrumentsRegistry::TemplatizedGlobalUInt64CounterHandle<2, 0>
GlobalInstrumentsRegistry::RegisterUInt64Counter<2, 0>(
absl::string_view name, absl::string_view description,
absl::string_view unit, std::array<absl::string_view, 2> label_keys,
std::array<absl::string_view, 0> optional_label_keys,
bool enable_by_default) {
TemplatizedGlobalUInt64CounterHandle<2, 0> handle;
handle.index = RegisterInstrument(
ValueType::kUInt64, InstrumentType::kCounter, name, description, unit,
label_keys, optional_label_keys, enable_by_default);
return handle;
}

template <>
GlobalInstrumentsRegistry::TemplatizedGlobalUInt64CounterHandle<4, 0>
GlobalInstrumentsRegistry::RegisterUInt64Counter<4, 0>(
absl::string_view name, absl::string_view description,
absl::string_view unit, std::array<absl::string_view, 4> label_keys,
std::array<absl::string_view, 0> optional_label_keys,
bool enable_by_default) {
TemplatizedGlobalUInt64CounterHandle<4, 0> handle;
handle.index = RegisterInstrument(
ValueType::kUInt64, InstrumentType::kCounter, name, description, unit,
label_keys, optional_label_keys, enable_by_default);
return handle;
}

template <>
GlobalInstrumentsRegistry::TemplatizedGlobalUInt64CounterHandle<1, 1>
GlobalInstrumentsRegistry::RegisterUInt64Counter<1, 1>(
absl::string_view name, absl::string_view description,
absl::string_view unit, std::array<absl::string_view, 1> label_keys,
std::array<absl::string_view, 1> optional_label_keys,
bool enable_by_default) {
TemplatizedGlobalUInt64CounterHandle<1, 1> handle;
handle.index = RegisterInstrument(
ValueType::kUInt64, InstrumentType::kCounter, name, description, unit,
label_keys, optional_label_keys, enable_by_default);
return handle;
}

template <std::size_t M, std::size_t N>
GlobalInstrumentsRegistry::TemplatizedGlobalDoubleCounterHandle<M, N>
GlobalInstrumentsRegistry::RegisterDoubleCounter(
absl::string_view name, absl::string_view description,
absl::string_view unit, absl::Span<const absl::string_view> label_keys,
absl::Span<const absl::string_view> optional_label_keys,
absl::string_view unit, std::array<absl::string_view, M> label_keys,
std::array<absl::string_view, N> optional_label_keys,
bool enable_by_default) {
auto& instruments = GetInstrumentList();
for (const auto& descriptor : instruments) {
Expand All @@ -91,7 +168,7 @@ GlobalInstrumentsRegistry::RegisterDoubleCounter(
descriptor.optional_label_keys = {optional_label_keys.begin(),
optional_label_keys.end()};
instruments.push_back(std::move(descriptor));
GlobalDoubleCounterHandle handle;
TemplatizedGlobalDoubleCounterHandle<M, N> handle;
handle.index = index;
return handle;
}
Expand Down
49 changes: 38 additions & 11 deletions src/core/lib/channel/metrics.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#ifndef GRPC_SRC_CORE_LIB_CHANNEL_METRICS_H
#define GRPC_SRC_CORE_LIB_CHANNEL_METRICS_H

#include <cstddef>
#include <cstdint>
#include <memory>
#include <vector>
Expand Down Expand Up @@ -86,17 +87,35 @@ class GlobalInstrumentsRegistry {
struct GlobalCallbackDoubleGaugeHandle : public GlobalInstrumentHandle {};
using GlobalCallbackHandle = absl::variant<GlobalCallbackInt64GaugeHandle,
GlobalCallbackDoubleGaugeHandle>;
template <std::size_t M, std::size_t N>
struct TemplatizedGlobalUInt64CounterHandle : public GlobalInstrumentHandle {
GlobalUInt64CounterHandle convert() {
GlobalUInt64CounterHandle handle;
handle.index = index;
return handle;
}
};
template <std::size_t M, std::size_t N>
struct TemplatizedGlobalDoubleCounterHandle : public GlobalInstrumentHandle {
GlobalDoubleCounterHandle convert() {
GlobalDoubleCounterHandle handle;
handle.index = index;
return handle;
}
};

// Creates instrument in the GlobalInstrumentsRegistry.
static GlobalUInt64CounterHandle RegisterUInt64Counter(
template <std::size_t M, std::size_t N>
static TemplatizedGlobalUInt64CounterHandle<M, N> RegisterUInt64Counter(
absl::string_view name, absl::string_view description,
absl::string_view unit, absl::Span<const absl::string_view> label_keys,
absl::Span<const absl::string_view> optional_label_keys,
absl::string_view unit, std::array<absl::string_view, M> label_keys,
std::array<absl::string_view, N> optional_label_keys,
bool enable_by_default);
static GlobalDoubleCounterHandle RegisterDoubleCounter(
template <std::size_t M, std::size_t N>
static TemplatizedGlobalDoubleCounterHandle<M, N> RegisterDoubleCounter(
absl::string_view name, absl::string_view description,
absl::string_view unit, absl::Span<const absl::string_view> label_keys,
absl::Span<const absl::string_view> optional_label_keys,
absl::string_view unit, std::array<absl::string_view, M> label_keys,
std::array<absl::string_view, N> optional_label_keys,
bool enable_by_default);
static GlobalUInt64HistogramHandle RegisterUInt64Histogram(
absl::string_view name, absl::string_view description,
Expand Down Expand Up @@ -131,6 +150,12 @@ class GlobalInstrumentsRegistry {

static std::vector<GlobalInstrumentsRegistry::GlobalInstrumentDescriptor>&
GetInstrumentList();
static InstrumentID RegisterInstrument(
ValueType value_type, InstrumentType instrument_type,
absl::string_view name, absl::string_view description,
absl::string_view unit, absl::Span<const absl::string_view> label_keys,
absl::Span<const absl::string_view> optional_label_keys,
bool enable_by_default);
};

// An interface for implementing callback-style metrics.
Expand Down Expand Up @@ -255,12 +280,14 @@ class GlobalStatsPluginRegistry {
}
// Adds a counter in all stats plugins within the group. See the StatsPlugin
// interface for more documentation and valid types.
template <class HandleType, class ValueType>
void AddCounter(HandleType handle, ValueType value,
absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) {
template <template <std::size_t, std::size_t> class HandleType,
std::size_t M, std::size_t N, typename ValueType>
void AddCounter(HandleType<M, N> handle, ValueType value,
std::array<absl::string_view, M> label_values,
std::array<absl::string_view, N> optional_values) {
for (auto& state : plugins_state_) {
state.plugin->AddCounter(handle, value, label_values, optional_values);
state.plugin->AddCounter(handle.convert(), value, label_values,
optional_values);
}
}
// Records a value to a histogram in all stats plugins within the group. See
Expand Down
9 changes: 6 additions & 3 deletions src/core/load_balancing/pick_first/pick_first.cc
Original file line number Diff line number Diff line change
Expand Up @@ -78,24 +78,27 @@ namespace {

constexpr absl::string_view kPickFirst = "pick_first";

std::array<absl::string_view, 1> kLabelKeys = {kMetricLabelTarget};
std::array<absl::string_view, 0> kEmptyOptionalLabelKeys = {};

const auto kMetricDisconnections =
GlobalInstrumentsRegistry::RegisterUInt64Counter(
"grpc.lb.pick_first.disconnections",
"EXPERIMENTAL. Number of times the selected subchannel becomes "
"disconnected.",
"{disconnection}", {kMetricLabelTarget}, {}, false);
"{disconnection}", kLabelKeys, kEmptyOptionalLabelKeys, false);

const auto kMetricConnectionAttemptsSucceeded =
GlobalInstrumentsRegistry::RegisterUInt64Counter(
"grpc.lb.pick_first.connection_attempts_succeeded",
"EXPERIMENTAL. Number of successful connection attempts.", "{attempt}",
{kMetricLabelTarget}, {}, false);
kLabelKeys, kEmptyOptionalLabelKeys, false);

const auto kMetricConnectionAttemptsFailed =
GlobalInstrumentsRegistry::RegisterUInt64Counter(
"grpc.lb.pick_first.connection_attempts_failed",
"EXPERIMENTAL. Number of failed connection attempts.", "{attempt}",
{kMetricLabelTarget}, {}, false);
kLabelKeys, kEmptyOptionalLabelKeys, false);

class PickFirstConfig final : public LoadBalancingPolicy::Config {
public:
Expand Down
25 changes: 14 additions & 11 deletions src/core/load_balancing/rls/rls.cc
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,13 @@ constexpr absl::string_view kMetricRlsDataPlaneTarget =
"grpc.lb.rls.data_plane_target";
constexpr absl::string_view kMetricLabelPickResult = "grpc.lb.pick_result";

std::array<absl::string_view, 4> kLabelKeys4 = {
kMetricLabelTarget, kMetricLabelRlsServerTarget, kMetricRlsDataPlaneTarget,
kMetricLabelPickResult};
std::array<absl::string_view, 2> kLabelKeys2 = {kMetricLabelTarget,
kMetricLabelRlsServerTarget};
std::array<absl::string_view, 0> kEmptyOptionalLabelKeys = {};

const auto kMetricCacheSize =
GlobalInstrumentsRegistry::RegisterCallbackInt64Gauge(
"grpc.lb.rls.cache_size", "EXPERIMENTAL. Size of the RLS cache.", "By",
Expand All @@ -143,10 +150,7 @@ const auto kMetricDefaultTargetPicks =
GlobalInstrumentsRegistry::RegisterUInt64Counter(
"grpc.lb.rls.default_target_picks",
"EXPERIMENTAL. Number of LB picks sent to the default target.",
"{pick}",
{kMetricLabelTarget, kMetricLabelRlsServerTarget,
kMetricRlsDataPlaneTarget, kMetricLabelPickResult},
{}, false);
"{pick}", kLabelKeys4, kEmptyOptionalLabelKeys, false);

const auto kMetricTargetPicks =
GlobalInstrumentsRegistry::RegisterUInt64Counter(
Expand All @@ -155,17 +159,14 @@ const auto kMetricTargetPicks =
"if the default target is also returned by the RLS server, RPCs sent "
"to that target from the cache will be counted in this metric, not "
"in grpc.rls.default_target_picks.",
"{pick}",
{kMetricLabelTarget, kMetricLabelRlsServerTarget,
kMetricRlsDataPlaneTarget, kMetricLabelPickResult},
{}, false);
"{pick}", kLabelKeys4, kEmptyOptionalLabelKeys, false);

const auto kMetricFailedPicks =
GlobalInstrumentsRegistry::RegisterUInt64Counter(
"grpc.lb.rls.failed_picks",
"EXPERIMENTAL. Number of LB picks failed due to either a failed RLS "
"request or the RLS channel being throttled.",
"{pick}", {kMetricLabelTarget, kMetricLabelRlsServerTarget}, {}, false);
"{pick}", kLabelKeys2, kEmptyOptionalLabelKeys, false);

constexpr absl::string_view kRls = "rls_experimental";
const char kGrpc[] = "grpc";
Expand Down Expand Up @@ -754,7 +755,8 @@ class RlsLb final : public LoadBalancingPolicy {
void UpdatePickerLocked() ABSL_LOCKS_EXCLUDED(&mu_);

void MaybeExportPickCount(
GlobalInstrumentsRegistry::GlobalUInt64CounterHandle handle,
GlobalInstrumentsRegistry::TemplatizedGlobalUInt64CounterHandle<4, 0>
handle,
absl::string_view target, const PickResult& pick_result);

const std::string instance_uuid_;
Expand Down Expand Up @@ -2223,7 +2225,8 @@ void RlsLb::UpdatePickerLocked() {
}

void RlsLb::MaybeExportPickCount(
GlobalInstrumentsRegistry::GlobalUInt64CounterHandle handle,
GlobalInstrumentsRegistry::TemplatizedGlobalUInt64CounterHandle<4, 0>
handle,
absl::string_view target, const PickResult& pick_result) {
absl::string_view pick_result_string = Match(
pick_result.result,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,15 @@ constexpr absl::string_view kWeightedRoundRobin = "weighted_round_robin";

constexpr absl::string_view kMetricLabelLocality = "grpc.lb.locality";

std::array<absl::string_view, 1> kLabelKeys = {kMetricLabelTarget};
std::array<absl::string_view, 1> kOptionalLabelKeys = {kMetricLabelLocality};

const auto kMetricRrFallback = GlobalInstrumentsRegistry::RegisterUInt64Counter(
"grpc.lb.wrr.rr_fallback",
"EXPERIMENTAL. Number of scheduler updates in which there were not "
"enough endpoints with valid weight, which caused the WRR policy to "
"fall back to RR behavior.",
"{update}", {kMetricLabelTarget}, {kMetricLabelLocality}, false);
"{update}", kLabelKeys, kOptionalLabelKeys, false);

const auto kMetricEndpointWeightNotYetUsable =
GlobalInstrumentsRegistry::RegisterUInt64Counter(
Expand All @@ -98,14 +101,14 @@ const auto kMetricEndpointWeightNotYetUsable =
"don't yet have usable weight information (i.e., either the load "
"report has not yet been received, or it is within the blackout "
"period).",
"{endpoint}", {kMetricLabelTarget}, {kMetricLabelLocality}, false);
"{endpoint}", kLabelKeys, kOptionalLabelKeys, false);

const auto kMetricEndpointWeightStale =
GlobalInstrumentsRegistry::RegisterUInt64Counter(
"grpc.lb.wrr.endpoint_weight_stale",
"EXPERIMENTAL. Number of endpoints from each scheduler update whose "
"latest weight is older than the expiration period.",
"{endpoint}", {kMetricLabelTarget}, {kMetricLabelLocality}, false);
"{endpoint}", kLabelKeys, kOptionalLabelKeys, false);

const auto kMetricEndpointWeights =
GlobalInstrumentsRegistry::RegisterDoubleHistogram(
Expand Down