| // |
| // |
| // Copyright 2023 gRPC authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| // |
| |
| #include "src/cpp/ext/otel/otel_plugin.h" |
| |
| #include "absl/functional/any_invocable.h" |
| #include "api/include/opentelemetry/metrics/provider.h" |
| #include "gmock/gmock.h" |
| #include "gtest/gtest.h" |
| #include "opentelemetry/sdk/metrics/meter_provider.h" |
| #include "opentelemetry/sdk/metrics/metric_reader.h" |
| |
| #include <grpcpp/grpcpp.h> |
| |
| #include "src/core/lib/channel/call_tracer.h" |
| #include "src/core/lib/config/core_configuration.h" |
| #include "test/core/util/test_config.h" |
| #include "test/cpp/end2end/test_service_impl.h" |
| #include "test/cpp/ext/otel/otel_test_library.h" |
| |
| namespace grpc { |
| namespace testing { |
| namespace { |
| |
| TEST(OTelPluginBuildTest, ApiDependency) { |
| opentelemetry::metrics::Provider::GetMeterProvider(); |
| } |
| |
| TEST(OTelPluginBuildTest, SdkDependency) { |
| opentelemetry::sdk::metrics::MeterProvider(); |
| } |
| |
| TEST_F(OTelPluginEnd2EndTest, ClientAttemptStarted) { |
| Init({grpc::internal::OTelClientAttemptStartedInstrumentName()}); |
| SendRPC(); |
| const char* kMetricName = "grpc.client.attempt.started"; |
| auto data = ReadCurrentMetricsData( |
| [&](const absl::flat_hash_map< |
| std::string, |
| std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>& |
| data) { return !data.contains(kMetricName); }); |
| ASSERT_EQ(data[kMetricName].size(), 1); |
| auto point_data = absl::get_if<opentelemetry::sdk::metrics::SumPointData>( |
| &data[kMetricName][0].point_data); |
| ASSERT_NE(point_data, nullptr); |
| auto client_started_value = absl::get_if<int64_t>(&point_data->value_); |
| ASSERT_NE(client_started_value, nullptr); |
| EXPECT_EQ(*client_started_value, 1); |
| const auto& attributes = data[kMetricName][0].attributes.GetAttributes(); |
| EXPECT_EQ(attributes.size(), 2); |
| const auto* method_value = |
| absl::get_if<std::string>(&attributes.at("grpc.method")); |
| ASSERT_NE(method_value, nullptr); |
| EXPECT_EQ(*method_value, kMethodName); |
| const auto* target_value = |
| absl::get_if<std::string>(&attributes.at("grpc.target")); |
| ASSERT_NE(target_value, nullptr); |
| EXPECT_EQ(*target_value, canonical_server_address_); |
| } |
| |
| TEST_F(OTelPluginEnd2EndTest, ClientAttemptDuration) { |
| Init({grpc::internal::OTelClientAttemptDurationInstrumentName()}); |
| SendRPC(); |
| const char* kMetricName = "grpc.client.attempt.duration"; |
| auto data = ReadCurrentMetricsData( |
| [&](const absl::flat_hash_map< |
| std::string, |
| std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>& |
| data) { return !data.contains(kMetricName); }); |
| ASSERT_EQ(data[kMetricName].size(), 1); |
| auto point_data = |
| absl::get_if<opentelemetry::sdk::metrics::HistogramPointData>( |
| &data[kMetricName][0].point_data); |
| ASSERT_NE(point_data, nullptr); |
| ASSERT_EQ(point_data->count_, 1); |
| const auto& attributes = data[kMetricName][0].attributes.GetAttributes(); |
| EXPECT_EQ(attributes.size(), 3); |
| const auto* method_value = |
| absl::get_if<std::string>(&attributes.at("grpc.method")); |
| ASSERT_NE(method_value, nullptr); |
| EXPECT_EQ(*method_value, kMethodName); |
| const auto* target_value = |
| absl::get_if<std::string>(&attributes.at("grpc.target")); |
| ASSERT_NE(target_value, nullptr); |
| EXPECT_EQ(*target_value, canonical_server_address_); |
| const auto* status_value = |
| absl::get_if<std::string>(&attributes.at("grpc.status")); |
| ASSERT_NE(status_value, nullptr); |
| EXPECT_EQ(*status_value, "OK"); |
| } |
| |
| TEST_F(OTelPluginEnd2EndTest, ClientAttemptSentTotalCompressedMessageSize) { |
| Init({grpc::internal:: |
| OTelClientAttemptSentTotalCompressedMessageSizeInstrumentName()}); |
| SendRPC(); |
| const char* kMetricName = |
| "grpc.client.attempt.sent_total_compressed_message_size"; |
| auto data = ReadCurrentMetricsData( |
| [&](const absl::flat_hash_map< |
| std::string, |
| std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>& |
| data) { return !data.contains(kMetricName); }); |
| ASSERT_EQ(data[kMetricName].size(), 1); |
| auto point_data = |
| absl::get_if<opentelemetry::sdk::metrics::HistogramPointData>( |
| &data[kMetricName][0].point_data); |
| ASSERT_NE(point_data, nullptr); |
| ASSERT_EQ(point_data->count_, 1); |
| const auto& attributes = data[kMetricName][0].attributes.GetAttributes(); |
| EXPECT_EQ(attributes.size(), 3); |
| const auto* method_value = |
| absl::get_if<std::string>(&attributes.at("grpc.method")); |
| ASSERT_NE(method_value, nullptr); |
| EXPECT_EQ(*method_value, kMethodName); |
| const auto* target_value = |
| absl::get_if<std::string>(&attributes.at("grpc.target")); |
| ASSERT_NE(target_value, nullptr); |
| EXPECT_EQ(*target_value, canonical_server_address_); |
| const auto* status_value = |
| absl::get_if<std::string>(&attributes.at("grpc.status")); |
| ASSERT_NE(status_value, nullptr); |
| EXPECT_EQ(*status_value, "OK"); |
| } |
| |
| TEST_F(OTelPluginEnd2EndTest, ClientAttemptRcvdTotalCompressedMessageSize) { |
| Init({grpc::internal:: |
| OTelClientAttemptRcvdTotalCompressedMessageSizeInstrumentName()}); |
| SendRPC(); |
| const char* kMetricName = |
| "grpc.client.attempt.rcvd_total_compressed_message_size"; |
| auto data = ReadCurrentMetricsData( |
| [&](const absl::flat_hash_map< |
| std::string, |
| std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>& |
| data) { return !data.contains(kMetricName); }); |
| ASSERT_EQ(data[kMetricName].size(), 1); |
| auto point_data = |
| absl::get_if<opentelemetry::sdk::metrics::HistogramPointData>( |
| &data[kMetricName][0].point_data); |
| ASSERT_NE(point_data, nullptr); |
| ASSERT_EQ(point_data->count_, 1); |
| const auto& attributes = data[kMetricName][0].attributes.GetAttributes(); |
| EXPECT_EQ(attributes.size(), 3); |
| const auto* method_value = |
| absl::get_if<std::string>(&attributes.at("grpc.method")); |
| ASSERT_NE(method_value, nullptr); |
| EXPECT_EQ(*method_value, kMethodName); |
| const auto* target_value = |
| absl::get_if<std::string>(&attributes.at("grpc.target")); |
| ASSERT_NE(target_value, nullptr); |
| EXPECT_EQ(*target_value, canonical_server_address_); |
| const auto* status_value = |
| absl::get_if<std::string>(&attributes.at("grpc.status")); |
| ASSERT_NE(status_value, nullptr); |
| EXPECT_EQ(*status_value, "OK"); |
| } |
| |
| TEST_F(OTelPluginEnd2EndTest, ServerCallStarted) { |
| Init({grpc::internal::OTelServerCallStartedInstrumentName()}); |
| SendRPC(); |
| const char* kMetricName = "grpc.server.call.started"; |
| auto data = ReadCurrentMetricsData( |
| [&](const absl::flat_hash_map< |
| std::string, |
| std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>& |
| data) { return !data.contains(kMetricName); }); |
| ASSERT_EQ(data[kMetricName].size(), 1); |
| auto point_data = absl::get_if<opentelemetry::sdk::metrics::SumPointData>( |
| &data[kMetricName][0].point_data); |
| ASSERT_NE(point_data, nullptr); |
| auto server_started_value = absl::get_if<int64_t>(&point_data->value_); |
| ASSERT_NE(server_started_value, nullptr); |
| ASSERT_EQ(*server_started_value, 1); |
| const auto& attributes = data[kMetricName][0].attributes.GetAttributes(); |
| EXPECT_EQ(attributes.size(), 1); |
| const auto* method_value = |
| absl::get_if<std::string>(&attributes.at("grpc.method")); |
| ASSERT_NE(method_value, nullptr); |
| EXPECT_EQ(*method_value, kMethodName); |
| } |
| |
| TEST_F(OTelPluginEnd2EndTest, ServerCallDuration) { |
| Init({grpc::internal::OTelServerCallDurationInstrumentName()}); |
| SendRPC(); |
| const char* kMetricName = "grpc.server.call.duration"; |
| auto data = ReadCurrentMetricsData( |
| [&](const absl::flat_hash_map< |
| std::string, |
| std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>& |
| data) { return !data.contains(kMetricName); }); |
| ASSERT_EQ(data[kMetricName].size(), 1); |
| auto point_data = |
| absl::get_if<opentelemetry::sdk::metrics::HistogramPointData>( |
| &data[kMetricName][0].point_data); |
| ASSERT_NE(point_data, nullptr); |
| ASSERT_EQ(point_data->count_, 1); |
| const auto& attributes = data[kMetricName][0].attributes.GetAttributes(); |
| EXPECT_EQ(attributes.size(), 2); |
| const auto* method_value = |
| absl::get_if<std::string>(&attributes.at("grpc.method")); |
| ASSERT_NE(method_value, nullptr); |
| EXPECT_EQ(*method_value, kMethodName); |
| const auto* status_value = |
| absl::get_if<std::string>(&attributes.at("grpc.status")); |
| ASSERT_NE(status_value, nullptr); |
| EXPECT_EQ(*status_value, "OK"); |
| } |
| |
| TEST_F(OTelPluginEnd2EndTest, ServerCallSentTotalCompressedMessageSize) { |
| Init({grpc::internal:: |
| OTelServerCallSentTotalCompressedMessageSizeInstrumentName()}); |
| SendRPC(); |
| const char* kMetricName = |
| "grpc.server.call.sent_total_compressed_message_size"; |
| auto data = ReadCurrentMetricsData( |
| [&](const absl::flat_hash_map< |
| std::string, |
| std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>& |
| data) { return !data.contains(kMetricName); }); |
| ASSERT_EQ(data[kMetricName].size(), 1); |
| auto point_data = |
| absl::get_if<opentelemetry::sdk::metrics::HistogramPointData>( |
| &data[kMetricName][0].point_data); |
| ASSERT_NE(point_data, nullptr); |
| EXPECT_EQ(point_data->count_, 1); |
| const auto& attributes = data[kMetricName][0].attributes.GetAttributes(); |
| EXPECT_EQ(attributes.size(), 2); |
| const auto* method_value = |
| absl::get_if<std::string>(&attributes.at("grpc.method")); |
| ASSERT_NE(method_value, nullptr); |
| EXPECT_EQ(*method_value, kMethodName); |
| const auto* status_value = |
| absl::get_if<std::string>(&attributes.at("grpc.status")); |
| ASSERT_NE(status_value, nullptr); |
| EXPECT_EQ(*status_value, "OK"); |
| } |
| |
| TEST_F(OTelPluginEnd2EndTest, ServerCallRcvdTotalCompressedMessageSize) { |
| Init({grpc::internal:: |
| OTelServerCallRcvdTotalCompressedMessageSizeInstrumentName()}); |
| SendRPC(); |
| const char* kMetricName = |
| "grpc.server.call.rcvd_total_compressed_message_size"; |
| auto data = ReadCurrentMetricsData( |
| [&](const absl::flat_hash_map< |
| std::string, |
| std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>& |
| data) { return !data.contains(kMetricName); }); |
| ASSERT_EQ(data[kMetricName].size(), 1); |
| auto point_data = |
| absl::get_if<opentelemetry::sdk::metrics::HistogramPointData>( |
| &data[kMetricName][0].point_data); |
| ASSERT_NE(point_data, nullptr); |
| ASSERT_EQ(point_data->count_, 1); |
| const auto& attributes = data[kMetricName][0].attributes.GetAttributes(); |
| EXPECT_EQ(attributes.size(), 2); |
| const auto* method_value = |
| absl::get_if<std::string>(&attributes.at("grpc.method")); |
| ASSERT_NE(method_value, nullptr); |
| EXPECT_EQ(*method_value, kMethodName); |
| const auto* status_value = |
| absl::get_if<std::string>(&attributes.at("grpc.status")); |
| ASSERT_NE(status_value, nullptr); |
| EXPECT_EQ(*status_value, "OK"); |
| } |
| |
| // Make sure that no meter provider results in normal operations. |
| TEST_F(OTelPluginEnd2EndTest, NoMeterProviderRegistered) { |
| Init({grpc::internal::OTelClientAttemptStartedInstrumentName()}, |
| /*resource=*/opentelemetry::sdk::resource::Resource::Create({}), |
| /*labels_injector=*/nullptr, |
| /*test_no_meter_provider=*/true); |
| SendRPC(); |
| } |
| |
| // Test that a channel selector returning true records metrics on the channel. |
| TEST_F(OTelPluginEnd2EndTest, TargetSelectorReturnsTrue) { |
| Init({grpc::internal::OTelClientAttemptStartedInstrumentName()}, /*resource=*/ |
| opentelemetry::sdk::resource::Resource::Create({}), |
| /*labels_injector=*/nullptr, |
| /*test_no_meter_provider=*/false, |
| /*target_selector=*/ |
| [](absl::string_view /*target*/) { return true; }); |
| SendRPC(); |
| const char* kMetricName = "grpc.client.attempt.started"; |
| auto data = ReadCurrentMetricsData( |
| [&](const absl::flat_hash_map< |
| std::string, |
| std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>& |
| data) { return !data.contains(kMetricName); }); |
| ASSERT_EQ(data[kMetricName].size(), 1); |
| auto point_data = absl::get_if<opentelemetry::sdk::metrics::SumPointData>( |
| &data[kMetricName][0].point_data); |
| ASSERT_NE(point_data, nullptr); |
| auto client_started_value = absl::get_if<int64_t>(&point_data->value_); |
| ASSERT_NE(client_started_value, nullptr); |
| EXPECT_EQ(*client_started_value, 1); |
| const auto& attributes = data[kMetricName][0].attributes.GetAttributes(); |
| EXPECT_EQ(attributes.size(), 2); |
| const auto* method_value = |
| absl::get_if<std::string>(&attributes.at("grpc.method")); |
| ASSERT_NE(method_value, nullptr); |
| EXPECT_EQ(*method_value, kMethodName); |
| const auto* target_value = |
| absl::get_if<std::string>(&attributes.at("grpc.target")); |
| ASSERT_NE(target_value, nullptr); |
| EXPECT_EQ(*target_value, canonical_server_address_); |
| } |
| |
| // Test that a target selector returning false does not record metrics on the |
| // channel. |
| TEST_F(OTelPluginEnd2EndTest, TargetSelectorReturnsFalse) { |
| Init({grpc::internal::OTelClientAttemptStartedInstrumentName()}, /*resource=*/ |
| opentelemetry::sdk::resource::Resource::Create({}), |
| /*labels_injector=*/nullptr, |
| /*test_no_meter_provider=*/false, |
| /*target_selector=*/ |
| [](absl::string_view /*target*/) { return false; }); |
| SendRPC(); |
| auto data = ReadCurrentMetricsData( |
| [&](const absl::flat_hash_map< |
| std::string, |
| std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>& |
| /*data*/) { return false; }); |
| ASSERT_TRUE(data.empty()); |
| } |
| |
| // Test that a target attribute filter returning true records metrics with the |
| // target as is on the channel. |
| TEST_F(OTelPluginEnd2EndTest, TargetAttributeFilterReturnsTrue) { |
| Init({grpc::internal::OTelClientAttemptStartedInstrumentName()}, /*resource=*/ |
| opentelemetry::sdk::resource::Resource::Create({}), |
| /*labels_injector=*/nullptr, |
| /*test_no_meter_provider=*/false, |
| /*target_selector=*/absl::AnyInvocable<bool(absl::string_view) const>(), |
| /*target_attribute_filter=*/[](absl::string_view /*target*/) { |
| return true; |
| }); |
| SendRPC(); |
| const char* kMetricName = "grpc.client.attempt.started"; |
| auto data = ReadCurrentMetricsData( |
| [&](const absl::flat_hash_map< |
| std::string, |
| std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>& |
| data) { return !data.contains(kMetricName); }); |
| ASSERT_EQ(data[kMetricName].size(), 1); |
| auto point_data = absl::get_if<opentelemetry::sdk::metrics::SumPointData>( |
| &data[kMetricName][0].point_data); |
| ASSERT_NE(point_data, nullptr); |
| auto client_started_value = absl::get_if<int64_t>(&point_data->value_); |
| ASSERT_NE(client_started_value, nullptr); |
| EXPECT_EQ(*client_started_value, 1); |
| const auto& attributes = data[kMetricName][0].attributes.GetAttributes(); |
| EXPECT_EQ(attributes.size(), 2); |
| const auto* method_value = |
| absl::get_if<std::string>(&attributes.at("grpc.method")); |
| ASSERT_NE(method_value, nullptr); |
| EXPECT_EQ(*method_value, kMethodName); |
| const auto* target_value = |
| absl::get_if<std::string>(&attributes.at("grpc.target")); |
| ASSERT_NE(target_value, nullptr); |
| EXPECT_EQ(*target_value, canonical_server_address_); |
| } |
| |
| // Test that a target attribute filter returning false records metrics with the |
| // target as "other". |
| TEST_F(OTelPluginEnd2EndTest, TargetAttributeFilterReturnsFalse) { |
| Init({grpc::internal::OTelClientAttemptStartedInstrumentName()}, /*resource=*/ |
| opentelemetry::sdk::resource::Resource::Create({}), |
| /*labels_injector=*/nullptr, |
| /*test_no_meter_provider=*/false, |
| /*target_selector=*/absl::AnyInvocable<bool(absl::string_view) const>(), |
| /*target_attribute_filter=*/ |
| [server_address = canonical_server_address_]( |
| absl::string_view /*target*/) { return false; }); |
| SendRPC(); |
| const char* kMetricName = "grpc.client.attempt.started"; |
| auto data = ReadCurrentMetricsData( |
| [&](const absl::flat_hash_map< |
| std::string, |
| std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>& |
| /*data*/) { return false; }); |
| ASSERT_EQ(data[kMetricName].size(), 1); |
| auto point_data = absl::get_if<opentelemetry::sdk::metrics::SumPointData>( |
| &data[kMetricName][0].point_data); |
| ASSERT_NE(point_data, nullptr); |
| auto client_started_value = absl::get_if<int64_t>(&point_data->value_); |
| ASSERT_NE(client_started_value, nullptr); |
| EXPECT_EQ(*client_started_value, 1); |
| const auto& attributes = data[kMetricName][0].attributes.GetAttributes(); |
| EXPECT_EQ(attributes.size(), 2); |
| const auto* method_value = |
| absl::get_if<std::string>(&attributes.at("grpc.method")); |
| ASSERT_NE(method_value, nullptr); |
| EXPECT_EQ(*method_value, kMethodName); |
| const auto* target_value = |
| absl::get_if<std::string>(&attributes.at("grpc.target")); |
| ASSERT_NE(target_value, nullptr); |
| EXPECT_EQ(*target_value, "other"); |
| } |
| |
| // Test that generic method names are scrubbed properly on the client side. |
| TEST_F(OTelPluginEnd2EndTest, GenericClientRpc) { |
| Init({grpc::internal::OTelClientAttemptStartedInstrumentName()}); |
| SendGenericRPC(); |
| const char* kMetricName = "grpc.client.attempt.started"; |
| auto data = ReadCurrentMetricsData( |
| [&](const absl::flat_hash_map< |
| std::string, |
| std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>& |
| /*data*/) { return false; }); |
| ASSERT_EQ(data[kMetricName].size(), 1); |
| auto point_data = absl::get_if<opentelemetry::sdk::metrics::SumPointData>( |
| &data[kMetricName][0].point_data); |
| ASSERT_NE(point_data, nullptr); |
| auto client_started_value = absl::get_if<int64_t>(&point_data->value_); |
| ASSERT_NE(client_started_value, nullptr); |
| EXPECT_EQ(*client_started_value, 1); |
| const auto& attributes = data[kMetricName][0].attributes.GetAttributes(); |
| EXPECT_EQ(attributes.size(), 2); |
| const auto* method_value = |
| absl::get_if<std::string>(&attributes.at("grpc.method")); |
| ASSERT_NE(method_value, nullptr); |
| EXPECT_EQ(*method_value, "other"); |
| const auto* target_value = |
| absl::get_if<std::string>(&attributes.at("grpc.target")); |
| ASSERT_NE(target_value, nullptr); |
| EXPECT_EQ(*target_value, canonical_server_address_); |
| } |
| |
| // Test that generic method names are scrubbed properly on the client side if |
| // the method attribute filter is set and it returns false. |
| TEST_F(OTelPluginEnd2EndTest, |
| GenericClientRpcWithMethodAttributeFilterReturningFalse) { |
| Init({grpc::internal::OTelClientAttemptStartedInstrumentName()}, |
| /*resource=*/opentelemetry::sdk::resource::Resource::Create({}), |
| /*labels_injector=*/nullptr, |
| /*test_no_meter_provider=*/false, |
| /*target_selector=*/absl::AnyInvocable<bool(absl::string_view) const>(), |
| /*target_attribute_filter=*/ |
| absl::AnyInvocable<bool(absl::string_view) const>(), |
| /*generic_method_attribute_filter=*/ |
| [](absl::string_view /*generic_method*/) { return false; }); |
| SendGenericRPC(); |
| const char* kMetricName = "grpc.client.attempt.started"; |
| auto data = ReadCurrentMetricsData( |
| [&](const absl::flat_hash_map< |
| std::string, |
| std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>& |
| /*data*/) { return false; }); |
| ASSERT_EQ(data[kMetricName].size(), 1); |
| auto point_data = absl::get_if<opentelemetry::sdk::metrics::SumPointData>( |
| &data[kMetricName][0].point_data); |
| ASSERT_NE(point_data, nullptr); |
| auto client_started_value = absl::get_if<int64_t>(&point_data->value_); |
| ASSERT_NE(client_started_value, nullptr); |
| EXPECT_EQ(*client_started_value, 1); |
| const auto& attributes = data[kMetricName][0].attributes.GetAttributes(); |
| EXPECT_EQ(attributes.size(), 2); |
| const auto* method_value = |
| absl::get_if<std::string>(&attributes.at("grpc.method")); |
| ASSERT_NE(method_value, nullptr); |
| EXPECT_EQ(*method_value, "other"); |
| const auto* target_value = |
| absl::get_if<std::string>(&attributes.at("grpc.target")); |
| ASSERT_NE(target_value, nullptr); |
| EXPECT_EQ(*target_value, canonical_server_address_); |
| } |
| |
| // Test that generic method names is not scrubbed on the client side if |
| // the method attribute filter is set and it returns true. |
| TEST_F(OTelPluginEnd2EndTest, |
| GenericClientRpcWithMethodAttributeFilterReturningTrue) { |
| Init({grpc::internal::OTelClientAttemptStartedInstrumentName()}, |
| /*resource=*/opentelemetry::sdk::resource::Resource::Create({}), |
| /*labels_injector=*/nullptr, |
| /*test_no_meter_provider=*/false, |
| /*target_selector=*/absl::AnyInvocable<bool(absl::string_view) const>(), |
| /*target_attribute_filter=*/ |
| absl::AnyInvocable<bool(absl::string_view) const>(), |
| /*generic_method_attribute_filter=*/ |
| [](absl::string_view /*generic_method*/) { return true; }); |
| SendGenericRPC(); |
| const char* kMetricName = "grpc.client.attempt.started"; |
| auto data = ReadCurrentMetricsData( |
| [&](const absl::flat_hash_map< |
| std::string, |
| std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>& |
| /*data*/) { return false; }); |
| ASSERT_EQ(data[kMetricName].size(), 1); |
| auto point_data = absl::get_if<opentelemetry::sdk::metrics::SumPointData>( |
| &data[kMetricName][0].point_data); |
| ASSERT_NE(point_data, nullptr); |
| auto client_started_value = absl::get_if<int64_t>(&point_data->value_); |
| ASSERT_NE(client_started_value, nullptr); |
| EXPECT_EQ(*client_started_value, 1); |
| const auto& attributes = data[kMetricName][0].attributes.GetAttributes(); |
| EXPECT_EQ(attributes.size(), 2); |
| const auto* method_value = |
| absl::get_if<std::string>(&attributes.at("grpc.method")); |
| ASSERT_NE(method_value, nullptr); |
| EXPECT_EQ(*method_value, kGenericMethodName); |
| const auto* target_value = |
| absl::get_if<std::string>(&attributes.at("grpc.target")); |
| ASSERT_NE(target_value, nullptr); |
| EXPECT_EQ(*target_value, canonical_server_address_); |
| } |
| |
| // Test that generic method names are scrubbed properly on the server side. |
| TEST_F(OTelPluginEnd2EndTest, GenericServerRpc) { |
| Init({grpc::internal::OTelServerCallDurationInstrumentName()}); |
| SendGenericRPC(); |
| const char* kMetricName = "grpc.server.call.duration"; |
| auto data = ReadCurrentMetricsData( |
| [&](const absl::flat_hash_map< |
| std::string, |
| std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>& |
| data) { return !data.contains(kMetricName); }); |
| ASSERT_EQ(data[kMetricName].size(), 1); |
| auto point_data = |
| absl::get_if<opentelemetry::sdk::metrics::HistogramPointData>( |
| &data[kMetricName][0].point_data); |
| ASSERT_NE(point_data, nullptr); |
| ASSERT_EQ(point_data->count_, 1); |
| const auto& attributes = data[kMetricName][0].attributes.GetAttributes(); |
| EXPECT_EQ(attributes.size(), 2); |
| const auto* method_value = |
| absl::get_if<std::string>(&attributes.at("grpc.method")); |
| ASSERT_NE(method_value, nullptr); |
| EXPECT_EQ(*method_value, "other"); |
| const auto* status_value = |
| absl::get_if<std::string>(&attributes.at("grpc.status")); |
| ASSERT_NE(status_value, nullptr); |
| EXPECT_EQ(*status_value, "UNIMPLEMENTED"); |
| } |
| |
| // Test that generic method names are scrubbed properly on the server side if |
| // the method attribute filter is set and it returns false. |
| TEST_F(OTelPluginEnd2EndTest, |
| GenericServerRpcWithMethodAttributeFilterReturningFalse) { |
| Init({grpc::internal::OTelServerCallDurationInstrumentName()}, |
| /*resource=*/opentelemetry::sdk::resource::Resource::Create({}), |
| /*labels_injector=*/nullptr, |
| /*test_no_meter_provider=*/false, |
| /*target_selector=*/absl::AnyInvocable<bool(absl::string_view) const>(), |
| /*target_attribute_filter=*/ |
| absl::AnyInvocable<bool(absl::string_view) const>(), |
| /*generic_method_attribute_filter=*/ |
| [](absl::string_view /*generic_method*/) { return false; }); |
| SendGenericRPC(); |
| const char* kMetricName = "grpc.server.call.duration"; |
| auto data = ReadCurrentMetricsData( |
| [&](const absl::flat_hash_map< |
| std::string, |
| std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>& |
| data) { return !data.contains(kMetricName); }); |
| ASSERT_EQ(data[kMetricName].size(), 1); |
| auto point_data = |
| absl::get_if<opentelemetry::sdk::metrics::HistogramPointData>( |
| &data[kMetricName][0].point_data); |
| ASSERT_NE(point_data, nullptr); |
| ASSERT_EQ(point_data->count_, 1); |
| const auto& attributes = data[kMetricName][0].attributes.GetAttributes(); |
| EXPECT_EQ(attributes.size(), 2); |
| const auto* method_value = |
| absl::get_if<std::string>(&attributes.at("grpc.method")); |
| ASSERT_NE(method_value, nullptr); |
| EXPECT_EQ(*method_value, "other"); |
| const auto* status_value = |
| absl::get_if<std::string>(&attributes.at("grpc.status")); |
| ASSERT_NE(status_value, nullptr); |
| EXPECT_EQ(*status_value, "UNIMPLEMENTED"); |
| } |
| |
| // Test that generic method names are not scrubbed on the server side if |
| // the method attribute filter is set and it returns true. |
| TEST_F(OTelPluginEnd2EndTest, |
| GenericServerRpcWithMethodAttributeFilterReturningTrue) { |
| Init({grpc::internal::OTelServerCallDurationInstrumentName()}, |
| /*resource=*/opentelemetry::sdk::resource::Resource::Create({}), |
| /*labels_injector=*/nullptr, |
| /*test_no_meter_provider=*/false, |
| /*target_selector=*/absl::AnyInvocable<bool(absl::string_view) const>(), |
| /*target_attribute_filter=*/ |
| absl::AnyInvocable<bool(absl::string_view) const>(), |
| /*generic_method_attribute_filter=*/ |
| [](absl::string_view /*generic_method*/) { return true; }); |
| SendGenericRPC(); |
| const char* kMetricName = "grpc.server.call.duration"; |
| auto data = ReadCurrentMetricsData( |
| [&](const absl::flat_hash_map< |
| std::string, |
| std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>& |
| data) { return !data.contains(kMetricName); }); |
| ASSERT_EQ(data[kMetricName].size(), 1); |
| auto point_data = |
| absl::get_if<opentelemetry::sdk::metrics::HistogramPointData>( |
| &data[kMetricName][0].point_data); |
| ASSERT_NE(point_data, nullptr); |
| ASSERT_EQ(point_data->count_, 1); |
| const auto& attributes = data[kMetricName][0].attributes.GetAttributes(); |
| EXPECT_EQ(attributes.size(), 2); |
| const auto* method_value = |
| absl::get_if<std::string>(&attributes.at("grpc.method")); |
| ASSERT_NE(method_value, nullptr); |
| EXPECT_EQ(*method_value, kGenericMethodName); |
| const auto* status_value = |
| absl::get_if<std::string>(&attributes.at("grpc.status")); |
| ASSERT_NE(status_value, nullptr); |
| EXPECT_EQ(*status_value, "UNIMPLEMENTED"); |
| } |
| |
| } // namespace |
| } // namespace testing |
| } // namespace grpc |
| |
| int main(int argc, char** argv) { |
| grpc::testing::TestEnvironment env(&argc, argv); |
| ::testing::InitGoogleTest(&argc, argv); |
| return RUN_ALL_TESTS(); |
| } |