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

[metrics] Templatized Metrics API #36449

Closed
wants to merge 16 commits into from
46 changes: 26 additions & 20 deletions src/core/ext/xds/xds_client_grpc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -99,20 +99,20 @@ const auto kMetricResourceUpdatesValid =
"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}", false)
.Labels(kMetricLabelTarget, kMetricLabelXdsServer,
kMetricLabelXdsResourceType)
.Build();

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}", false)
.Labels(kMetricLabelTarget, kMetricLabelXdsServer,
kMetricLabelXdsResourceType)
.Build();

const auto kMetricServerFailure =
GlobalInstrumentsRegistry::RegisterUInt64Counter(
Expand All @@ -121,7 +121,9 @@ 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}", false)
.Labels(kMetricLabelTarget, kMetricLabelXdsServer)
.Build();

const auto kMetricConnected =
GlobalInstrumentsRegistry::RegisterCallbackInt64Gauge(
Expand All @@ -132,15 +134,17 @@ const auto kMetricConnected =
"ADS stream fails without seeing a response message, as per gRFC "
"A57. It will be set to 1 when we receive the first response on "
"an ADS stream.",
"{bool}", {kMetricLabelTarget, kMetricLabelXdsServer}, {}, false);
"{bool}", false)
.Labels(kMetricLabelTarget, kMetricLabelXdsServer)
.Build();

const auto kMetricResources =
GlobalInstrumentsRegistry::RegisterCallbackInt64Gauge(
"grpc.xds_client.resources", "EXPERIMENTAL. Number of xDS resources.",
"{resource}",
{kMetricLabelTarget, kMetricLabelXdsAuthority,
kMetricLabelXdsResourceType, kMetricLabelXdsCacheState},
{}, false);
"{resource}", false)
.Labels(kMetricLabelTarget, kMetricLabelXdsAuthority,
kMetricLabelXdsResourceType, kMetricLabelXdsCacheState)
.Build();

} // namespace

Expand All @@ -167,7 +171,7 @@ class GrpcXdsClient::MetricsReporter final : public XdsMetricsReporter {

void ReportServerFailure(absl::string_view xds_server) override {
xds_client_.stats_plugin_group_.AddCounter(
kMetricServerFailure, 1, {xds_client_.key_, xds_server}, {});
kMetricServerFailure, uint64_t(1), {xds_client_.key_, xds_server}, {});
markdroth marked this conversation as resolved.
Show resolved Hide resolved
}

private:
Expand Down Expand Up @@ -313,10 +317,10 @@ GrpcXdsClient::GrpcXdsClient(
.certificate_providers())),
stats_plugin_group_(GetStatsPluginGroupForKey(key_)),
registered_metric_callback_(stats_plugin_group_.RegisterCallback(
[this](CallbackMetricReporter& reporter) {
[this](CallbackMetricReporterWrapper& reporter) {
ReportCallbackMetrics(reporter);
},
{kMetricConnected, kMetricResources})) {}
{kMetricConnected.convert(), kMetricResources.convert()})) {}
markdroth marked this conversation as resolved.
Show resolved Hide resolved

void GrpcXdsClient::Orphaned() {
registered_metric_callback_.reset();
Expand Down Expand Up @@ -380,16 +384,18 @@ grpc_slice GrpcXdsClient::DumpAllClientConfigs()
return grpc_slice_from_cpp_string(std::string(output, output_length));
}

void GrpcXdsClient::ReportCallbackMetrics(CallbackMetricReporter& reporter) {
void GrpcXdsClient::ReportCallbackMetrics(
CallbackMetricReporterWrapper& reporter) {
MutexLock lock(mu());
ReportResourceCounts([&](const ResourceCountLabels& labels, uint64_t count) {
reporter.Report(
kMetricResources, count,
kMetricResources, static_cast<int64_t>(count),
{key_, labels.xds_authority, labels.resource_type, labels.cache_state},
{});
});
ReportServerConnections([&](absl::string_view xds_server, bool connected) {
reporter.Report(kMetricConnected, connected, {key_, xds_server}, {});
reporter.Report(kMetricConnected, static_cast<int64_t>(connected),
{key_, xds_server}, {});
});
}

Expand Down
2 changes: 1 addition & 1 deletion src/core/ext/xds/xds_client_grpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ class GrpcXdsClient final : public XdsClient {
private:
class MetricsReporter;

void ReportCallbackMetrics(CallbackMetricReporter& reporter);
void ReportCallbackMetrics(CallbackMetricReporterWrapper& reporter);
void Orphaned() override;

std::string key_;
Expand Down
186 changes: 13 additions & 173 deletions src/core/lib/channel/metrics.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,26 @@ GlobalInstrumentsRegistry::GetInstrumentList() {
return *instruments;
}

GlobalInstrumentsRegistry::GlobalUInt64CounterHandle
GlobalInstrumentsRegistry::RegisterUInt64Counter(
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,
bool enable_by_default) {
absl::string_view unit, bool enable_by_default,
absl::Span<const absl::string_view> label_keys,
absl::Span<const absl::string_view> optional_label_keys) {
auto& instruments = GetInstrumentList();
for (const auto& descriptor : instruments) {
if (descriptor.name == name) {
Crash(
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,169 +61,7 @@ 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 handle;
}

GlobalInstrumentsRegistry::GlobalDoubleCounterHandle
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,
bool enable_by_default) {
auto& instruments = GetInstrumentList();
for (const auto& descriptor : instruments) {
if (descriptor.name == name) {
Crash(
absl::StrFormat("Metric name %s has already been registered.", name));
}
}
uint32_t index = instruments.size();
GPR_ASSERT(index < std::numeric_limits<uint32_t>::max());
GlobalInstrumentDescriptor descriptor;
descriptor.value_type = ValueType::kDouble;
descriptor.instrument_type = InstrumentType::kCounter;
descriptor.index = index;
descriptor.enable_by_default = enable_by_default;
descriptor.name = name;
descriptor.description = description;
descriptor.unit = unit;
descriptor.label_keys = {label_keys.begin(), label_keys.end()};
descriptor.optional_label_keys = {optional_label_keys.begin(),
optional_label_keys.end()};
instruments.push_back(std::move(descriptor));
GlobalDoubleCounterHandle handle;
handle.index = index;
return handle;
}

GlobalInstrumentsRegistry::GlobalUInt64HistogramHandle
GlobalInstrumentsRegistry::RegisterUInt64Histogram(
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) {
auto& instruments = GetInstrumentList();
for (const auto& descriptor : instruments) {
if (descriptor.name == name) {
Crash(
absl::StrFormat("Metric name %s has already been registered.", name));
}
}
uint32_t index = instruments.size();
GPR_ASSERT(index < std::numeric_limits<uint32_t>::max());
GlobalInstrumentDescriptor descriptor;
descriptor.value_type = ValueType::kUInt64;
descriptor.instrument_type = InstrumentType::kHistogram;
descriptor.index = index;
descriptor.enable_by_default = enable_by_default;
descriptor.name = name;
descriptor.description = description;
descriptor.unit = unit;
descriptor.label_keys = {label_keys.begin(), label_keys.end()};
descriptor.optional_label_keys = {optional_label_keys.begin(),
optional_label_keys.end()};
instruments.push_back(std::move(descriptor));
GlobalUInt64HistogramHandle handle;
handle.index = index;
return handle;
}

GlobalInstrumentsRegistry::GlobalDoubleHistogramHandle
GlobalInstrumentsRegistry::RegisterDoubleHistogram(
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) {
auto& instruments = GetInstrumentList();
for (const auto& descriptor : instruments) {
if (descriptor.name == name) {
Crash(
absl::StrFormat("Metric name %s has already been registered.", name));
}
}
uint32_t index = instruments.size();
GPR_ASSERT(index < std::numeric_limits<uint32_t>::max());
GlobalInstrumentDescriptor descriptor;
descriptor.value_type = ValueType::kDouble;
descriptor.instrument_type = InstrumentType::kHistogram;
descriptor.index = index;
descriptor.enable_by_default = enable_by_default;
descriptor.name = name;
descriptor.description = description;
descriptor.unit = unit;
descriptor.label_keys = {label_keys.begin(), label_keys.end()};
descriptor.optional_label_keys = {optional_label_keys.begin(),
optional_label_keys.end()};
instruments.push_back(std::move(descriptor));
GlobalDoubleHistogramHandle handle;
handle.index = index;
return handle;
}

GlobalInstrumentsRegistry::GlobalCallbackInt64GaugeHandle
GlobalInstrumentsRegistry::RegisterCallbackInt64Gauge(
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) {
auto& instruments = GetInstrumentList();
for (const auto& descriptor : instruments) {
if (descriptor.name == name) {
Crash(
absl::StrFormat("Metric name %s has already been registered.", name));
}
}
uint32_t index = instruments.size();
GPR_ASSERT(index < std::numeric_limits<uint32_t>::max());
GlobalInstrumentDescriptor descriptor;
descriptor.value_type = ValueType::kInt64;
descriptor.instrument_type = InstrumentType::kCallbackGauge;
descriptor.index = index;
descriptor.enable_by_default = enable_by_default;
descriptor.name = name;
descriptor.description = description;
descriptor.unit = unit;
descriptor.label_keys = {label_keys.begin(), label_keys.end()};
descriptor.optional_label_keys = {optional_label_keys.begin(),
optional_label_keys.end()};
instruments.push_back(std::move(descriptor));
GlobalCallbackInt64GaugeHandle handle;
handle.index = index;
return handle;
}

GlobalInstrumentsRegistry::GlobalCallbackDoubleGaugeHandle
GlobalInstrumentsRegistry::RegisterCallbackDoubleGauge(
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) {
auto& instruments = GetInstrumentList();
for (const auto& descriptor : instruments) {
if (descriptor.name == name) {
Crash(
absl::StrFormat("Metric name %s has already been registered.", name));
}
}
uint32_t index = instruments.size();
GPR_ASSERT(index < std::numeric_limits<uint32_t>::max());
GlobalInstrumentDescriptor descriptor;
descriptor.value_type = ValueType::kDouble;
descriptor.instrument_type = InstrumentType::kCallbackGauge;
descriptor.index = index;
descriptor.enable_by_default = enable_by_default;
descriptor.name = name;
descriptor.description = description;
descriptor.unit = unit;
descriptor.label_keys = {label_keys.begin(), label_keys.end()};
descriptor.optional_label_keys = {optional_label_keys.begin(),
optional_label_keys.end()};
instruments.push_back(std::move(descriptor));
GlobalCallbackDoubleGaugeHandle handle;
handle.index = index;
return handle;
return index;
}

void GlobalInstrumentsRegistry::ForEach(
Expand All @@ -239,7 +79,7 @@ GlobalInstrumentsRegistry::GetInstrumentDescriptor(

RegisteredMetricCallback::RegisteredMetricCallback(
GlobalStatsPluginRegistry::StatsPluginGroup& stats_plugin_group,
absl::AnyInvocable<void(CallbackMetricReporter&)> callback,
absl::AnyInvocable<void(CallbackMetricReporterWrapper&)> callback,
std::vector<GlobalInstrumentsRegistry::GlobalCallbackHandle> metrics,
Duration min_interval)
: stats_plugin_group_(stats_plugin_group),
Expand All @@ -259,7 +99,7 @@ RegisteredMetricCallback::~RegisteredMetricCallback() {

std::unique_ptr<RegisteredMetricCallback>
GlobalStatsPluginRegistry::StatsPluginGroup::RegisterCallback(
absl::AnyInvocable<void(CallbackMetricReporter&)> callback,
absl::AnyInvocable<void(CallbackMetricReporterWrapper&)> callback,
std::vector<GlobalInstrumentsRegistry::GlobalCallbackHandle> metrics,
Duration min_interval) {
return std::make_unique<RegisteredMetricCallback>(
Expand Down