Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 39 additions & 16 deletions google/cloud/bigtable/internal/grpc_metrics_exporter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -289,15 +289,11 @@ MonitoredResourceResult MakeMonitoredResource(
return MonitoredResourceResult{std::move(project_id), std::move(resource)};
}

void EnableGrpcMetrics(
GrpcMetricsPluginConfig MakeGrpcMetricsPluginConfig(
// NOLINTNEXTLINE(performance-unnecessary-value-param)
opentelemetry::sdk::resource::Resource detected_resource,
std::shared_ptr<monitoring_v3::MetricServiceConnection> const& conn,
Options const& options, std::string const& client_uid) {
auto authority = options.get<AuthorityOption>();
if (!GrpcMetricsExporterRegistry::Singleton().Register(authority)) return;

auto detector = otel::MakeResourceDetector();
auto detected_resource = detector->Detect();

auto dynamic_resource_fn =
[options, client_uid, detected_resource = std::move(detected_resource)](
opentelemetry::sdk::metrics::PointDataAttributes const& pda) {
Expand Down Expand Up @@ -357,7 +353,7 @@ void EnableGrpcMetrics(
auto provider =
MakeGrpcMeterProvider(std::move(exporter), std::move(reader_options));

auto const metrics = std::vector<std::string_view>{
auto metrics = std::vector<std::string_view>{
std::string_view{"grpc.client.attempt.duration"},
std::string_view{"grpc.lb.rls.default_target_picks"},
std::string_view{"grpc.lb.rls.target_picks"},
Expand All @@ -370,13 +366,14 @@ void EnableGrpcMetrics(
std::string_view{"grpc.subchannel.open_connections"},
};

auto const disable_metrics = std::vector<std::string_view>{
auto disable_metrics = std::vector<std::string_view>{
std::string_view{
"grpc.client.attempt.sent_total_compressed_message_size"},
std::string_view{
"grpc.client.attempt.rcvd_total_compressed_message_size"},
};

auto authority = options.get<AuthorityOption>();
auto scope_filter =
[authority = std::move(authority)](
grpc::OpenTelemetryPluginBuilder::ChannelScope const& scope) {
Expand All @@ -386,15 +383,41 @@ void EnableGrpcMetrics(
<< " vs expected authority=" << authority;
return scope.default_authority() == authority;
};

auto generic_method_filter = [](std::string_view target) {
return absl::StartsWith(target, "google.bigtable.v2");
};

return GrpcMetricsPluginConfig{
std::move(provider), std::move(metrics),
std::move(disable_metrics), std::move(generic_method_filter),
std::move(scope_filter),
};
}

GrpcMetricsPluginConfig MakeGrpcMetricsPluginConfig(
std::shared_ptr<monitoring_v3::MetricServiceConnection> const& conn,
Options const& options, std::string const& client_uid) {
auto detector = otel::MakeResourceDetector();
return MakeGrpcMetricsPluginConfig(detector->Detect(), conn, options,
client_uid);
}

void EnableGrpcMetrics(
std::shared_ptr<monitoring_v3::MetricServiceConnection> const& conn,
Options const& options, std::string const& client_uid) {
auto const& authority = options.get<AuthorityOption>();
if (!GrpcMetricsExporterRegistry::Singleton().Register(authority)) return;

auto config = MakeGrpcMetricsPluginConfig(conn, options, client_uid);
auto status =
grpc::OpenTelemetryPluginBuilder()
.SetMeterProvider(provider)
.EnableMetrics(metrics)
.DisableMetrics(disable_metrics)
.SetGenericMethodAttributeFilter([](std::string_view target) {
return absl::StartsWith(target, "google.bigtable.v2");
})
.SetChannelScopeFilter(std::move(scope_filter))
.SetMeterProvider(config.meter_provider)
.EnableMetrics(config.enabled_metrics)
.DisableMetrics(config.disabled_metrics)
.SetGenericMethodAttributeFilter(
std::move(config.generic_method_filter))
.SetChannelScopeFilter(std::move(config.channel_scope_filter))
.BuildAndRegisterGlobal();
if (!status.ok()) {
GCP_LOG(ERROR) << "Cannot register provider status=" << status.ToString();
Expand Down
21 changes: 21 additions & 0 deletions google/cloud/bigtable/internal/grpc_metrics_exporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,14 @@
#ifdef GOOGLE_CLOUD_CPP_BIGTABLE_WITH_GRPC_OTEL_METRICS
#include "google/cloud/monitoring/v3/metric_connection.h"
#include "google/api/monitored_resource.pb.h"
#include <grpcpp/ext/otel_plugin.h>
#include <opentelemetry/metrics/meter_provider.h>
#include <opentelemetry/sdk/metrics/data/metric_data.h>
#include <opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader.h>
#include <opentelemetry/sdk/metrics/push_metric_exporter.h>
#include <opentelemetry/sdk/resource/resource.h>
#include <functional>
#include <string_view>
#include <vector>
#endif // GOOGLE_CLOUD_CPP_BIGTABLE_WITH_GRPC_OTEL_METRICS

Expand Down Expand Up @@ -95,6 +98,24 @@ std::shared_ptr<opentelemetry::metrics::MeterProvider> MakeGrpcMeterProvider(
opentelemetry::sdk::metrics::PeriodicExportingMetricReaderOptions
reader_options);

struct GrpcMetricsPluginConfig {
std::shared_ptr<opentelemetry::metrics::MeterProvider> meter_provider;
std::vector<std::string_view> enabled_metrics;
std::vector<std::string_view> disabled_metrics;
std::function<bool(std::string_view)> generic_method_filter;
std::function<bool(grpc::OpenTelemetryPluginBuilder::ChannelScope const&)>
channel_scope_filter;
};

GrpcMetricsPluginConfig MakeGrpcMetricsPluginConfig(
opentelemetry::sdk::resource::Resource detected_resource,
std::shared_ptr<monitoring_v3::MetricServiceConnection> const& conn,
Options const& options, std::string const& client_uid);
Comment thread
scotthart marked this conversation as resolved.

GrpcMetricsPluginConfig MakeGrpcMetricsPluginConfig(
std::shared_ptr<monitoring_v3::MetricServiceConnection> const& conn,
Options const& options, std::string const& client_uid);

void EnableGrpcMetrics(
std::shared_ptr<monitoring_v3::MetricServiceConnection> const& conn,
Options const& options, std::string const& client_uid);
Expand Down
66 changes: 66 additions & 0 deletions google/cloud/bigtable/internal/grpc_metrics_exporter_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "google/cloud/bigtable/version.h"
#include "google/cloud/grpc_options.h"
#include "google/cloud/options.h"
#include <grpc/event_engine/endpoint_config.h>
#include <gmock/gmock.h>
#include <grpcpp/grpcpp.h>
#include <opentelemetry/metrics/meter.h>
Expand Down Expand Up @@ -57,6 +58,7 @@ using ::testing::Ge;
using ::testing::IsEmpty;
using ::testing::Le;
using ::testing::Not;
using ::testing::NotNull;
using ::testing::ResultOf;
using ::testing::Return;
using ::testing::SizeIs;
Expand Down Expand Up @@ -161,6 +163,19 @@ auto TestReaderOptions() {
return reader_options;
}

class DummyEndpointConfig
: public grpc_event_engine::experimental::EndpointConfig {
public:
~DummyEndpointConfig() override = default;
std::optional<int> GetInt(absl::string_view) const override {
return std::nullopt;
}
std::optional<absl::string_view> GetString(absl::string_view) const override {
return std::nullopt;
}
void* GetVoidPointer(absl::string_view) const override { return nullptr; }
};

class DummyMetricServiceConnection
: public monitoring_v3::MetricServiceConnection {
public:
Expand Down Expand Up @@ -393,6 +408,57 @@ TEST(GrpcMetricsExporterTest, ValidateGrpcClientAttemptDuration) {
}
}

TEST(GrpcMetricsExporterTest, ValidatePluginConfigArguments) {
Options options;
options.set<AuthorityOption>("custom-bigtable-authority.googleapis.com");
options.set<bigtable::AppProfileIdOption>("test-app-profile");
options.set<bigtable::MetricsPeriodOption>(std::chrono::seconds(60));
auto conn = std::make_shared<DummyMetricServiceConnection>();
std::string const client_uid = "test-client-uid";

auto config = MakeGrpcMetricsPluginConfig(conn, options, client_uid);

EXPECT_THAT(config.meter_provider, NotNull());

EXPECT_THAT(
config.enabled_metrics,
ElementsAre("grpc.client.attempt.duration",
"grpc.lb.rls.default_target_picks",
"grpc.lb.rls.target_picks", "grpc.lb.rls.failed_picks",
"grpc.xds_client.server_failure",
"grpc.xds_client.resource_updates_invalid",
"grpc.subchannel.disconnections",
"grpc.subchannel.connection_attempts_succeeded",
"grpc.subchannel.connection_attempts_failed",
"grpc.subchannel.open_connections"));

EXPECT_THAT(
config.disabled_metrics,
ElementsAre("grpc.client.attempt.sent_total_compressed_message_size",
"grpc.client.attempt.rcvd_total_compressed_message_size"));

ASSERT_TRUE(config.generic_method_filter);
EXPECT_TRUE(
config.generic_method_filter("google.bigtable.v2.Bigtable/ReadRows"));
EXPECT_TRUE(
config.generic_method_filter("google.bigtable.v2.Bigtable/MutateRow"));
EXPECT_FALSE(
config.generic_method_filter("google.storage.v2.Storage/ReadObject"));
EXPECT_FALSE(
config.generic_method_filter("google.spanner.v1.Spanner/ExecuteSql"));
EXPECT_FALSE(config.generic_method_filter(""));

ASSERT_TRUE(config.channel_scope_filter);
DummyEndpointConfig endpoint_config;
grpc::OpenTelemetryPluginBuilder::ChannelScope matching_scope(
"custom-target", "custom-bigtable-authority.googleapis.com",
endpoint_config);
grpc::OpenTelemetryPluginBuilder::ChannelScope non_matching_scope(
"custom-target", "other-authority.googleapis.com", endpoint_config);
EXPECT_TRUE(config.channel_scope_filter(matching_scope));
EXPECT_FALSE(config.channel_scope_filter(non_matching_scope));
}

} // namespace
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
} // namespace bigtable_internal
Expand Down
Loading