[Metrics] New OpenTelemetry Plugin Implementation of Stats Plugin (#36070)

<!--

If you know who should review your pull request, please assign it to that
person, otherwise the pull request would get assigned randomly.

If your pull request is for a specific language, please add the appropriate
lang label.

-->

Closes #36070

COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/36070 from yijiem:grpc-metrics 72653727b1
PiperOrigin-RevId: 618529035
This commit is contained in:
Yijie Ma 2024-03-23 19:34:26 -07:00 committed by Copybara-Service
parent 041c283ccc
commit c54c69dcdd
46 changed files with 2185 additions and 964 deletions

1
BUILD
View File

@ -1695,7 +1695,6 @@ grpc_cc_library(
language = "c++",
visibility = ["@grpc:alt_grpc_base_legacy"],
deps = [
"config",
"gpr",
"legacy_context",
"tcp_tracer",

96
CMakeLists.txt generated
View File

@ -5695,7 +5695,7 @@ endif()
if(gRPC_BUILD_GRPCPP_OTEL_PLUGIN)
add_library(grpcpp_otel_plugin
src/cpp/ext/otel/otel_client_filter.cc
src/cpp/ext/otel/otel_client_call_tracer.cc
src/cpp/ext/otel/otel_plugin.cc
src/cpp/ext/otel/otel_server_call_tracer.cc
)
@ -7560,6 +7560,7 @@ add_executable(bad_ping_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/bad_ping.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -8035,6 +8036,7 @@ add_executable(binary_metadata_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/binary_metadata.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -8474,6 +8476,7 @@ add_executable(call_creds_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/call_creds.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -8680,6 +8683,7 @@ add_executable(call_host_override_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/call_host_override.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -8785,6 +8789,7 @@ add_executable(cancel_after_accept_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/cancel_after_accept.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -8847,6 +8852,7 @@ add_executable(cancel_after_client_done_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/cancel_after_client_done.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -8909,6 +8915,7 @@ add_executable(cancel_after_invoke_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/cancel_after_invoke.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -8971,6 +8978,7 @@ add_executable(cancel_after_round_trip_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/cancel_after_round_trip.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -9080,6 +9088,7 @@ add_executable(cancel_before_invoke_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/cancel_before_invoke.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -9184,6 +9193,7 @@ add_executable(cancel_in_a_vacuum_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/cancel_in_a_vacuum.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -9246,6 +9256,7 @@ add_executable(cancel_with_status_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/cancel_with_status.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -10892,6 +10903,7 @@ add_executable(client_streaming_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/client_streaming.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -11230,6 +11242,7 @@ add_executable(compressed_payload_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/compressed_payload.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -11514,6 +11527,7 @@ add_executable(connectivity_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/connectivity.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -11942,6 +11956,7 @@ add_executable(default_host_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/default_host.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -12149,6 +12164,7 @@ add_executable(disappearing_server_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/disappearing_server.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -12468,6 +12484,7 @@ add_executable(empty_batch_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/empty_batch.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -13844,6 +13861,7 @@ add_executable(filter_causes_close_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/filter_causes_close.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -13906,6 +13924,7 @@ add_executable(filter_context_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/filter_context.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -13968,6 +13987,7 @@ add_executable(filter_init_fails_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/filter_init_fails.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -14080,6 +14100,7 @@ add_executable(filtered_metadata_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/filtered_metadata.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -14868,6 +14889,7 @@ add_executable(graceful_server_shutdown_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/graceful_server_shutdown.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -15233,6 +15255,7 @@ add_executable(grpc_authz_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/grpc_authz.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -16623,6 +16646,7 @@ add_executable(high_initial_seqno_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/high_initial_seqno.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -16931,6 +16955,7 @@ add_executable(hpack_size_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/hpack_size.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -17086,6 +17111,7 @@ add_executable(http2_stats_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/http2_stats.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -17978,6 +18004,7 @@ add_executable(invoke_large_request_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/invoke_large_request.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -18366,6 +18393,7 @@ add_executable(keepalive_timeout_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/keepalive_timeout.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -18471,6 +18499,7 @@ add_executable(large_metadata_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/large_metadata.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -19143,6 +19172,7 @@ add_executable(max_concurrent_streams_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/max_concurrent_streams.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -19205,6 +19235,7 @@ add_executable(max_connection_age_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/max_connection_age.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -19267,6 +19298,7 @@ add_executable(max_connection_idle_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/max_connection_idle.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -19329,6 +19361,7 @@ add_executable(max_message_length_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/max_message_length.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -20010,6 +20043,7 @@ add_executable(negative_deadline_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/negative_deadline.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -20104,6 +20138,7 @@ add_executable(no_logging_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/no_logging.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -20166,6 +20201,7 @@ add_executable(no_op_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/no_op.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -20633,9 +20669,10 @@ add_executable(otel_plugin_test
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/orca_load_report.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/orca_load_report.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/orca_load_report.grpc.pb.h
src/cpp/ext/otel/otel_client_filter.cc
src/cpp/ext/otel/otel_client_call_tracer.cc
src/cpp/ext/otel/otel_plugin.cc
src/cpp/ext/otel/otel_server_call_tracer.cc
test/core/util/fake_stats_plugin.cc
test/cpp/end2end/test_service_impl.cc
test/cpp/ext/otel/otel_plugin_test.cc
test/cpp/ext/otel/otel_test_library.cc
@ -21093,6 +21130,7 @@ add_executable(payload_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/payload.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -21467,6 +21505,7 @@ add_executable(ping_pong_streaming_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/ping_pong_streaming.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -21580,6 +21619,7 @@ add_executable(ping_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/ping.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -22573,6 +22613,7 @@ add_executable(proxy_auth_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/proxy_auth.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -23148,6 +23189,7 @@ add_executable(registered_call_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/registered_call.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -23254,6 +23296,7 @@ add_executable(request_with_flags_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/request_with_flags.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -23316,6 +23359,7 @@ add_executable(request_with_payload_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/request_with_payload.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -23649,6 +23693,7 @@ add_executable(resource_quota_server_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/resource_quota_server.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -23753,6 +23798,7 @@ add_executable(retry_cancel_after_first_attempt_starts_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_cancel_after_first_attempt_starts.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -23815,6 +23861,7 @@ add_executable(retry_cancel_during_delay_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_cancel_during_delay.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -23877,6 +23924,7 @@ add_executable(retry_cancel_with_multiple_send_batches_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_cancel_with_multiple_send_batches.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -23939,6 +23987,7 @@ add_executable(retry_cancellation_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_cancellation.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -24001,6 +24050,7 @@ add_executable(retry_disabled_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_disabled.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -24063,6 +24113,7 @@ add_executable(retry_exceeds_buffer_size_in_delay_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_exceeds_buffer_size_in_delay.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -24125,6 +24176,7 @@ add_executable(retry_exceeds_buffer_size_in_initial_batch_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -24187,6 +24239,7 @@ add_executable(retry_exceeds_buffer_size_in_subsequent_batch_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -24249,6 +24302,7 @@ add_executable(retry_lb_drop_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_lb_drop.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -24311,6 +24365,7 @@ add_executable(retry_lb_fail_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_lb_fail.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -24373,6 +24428,7 @@ add_executable(retry_non_retriable_status_before_trailers_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_non_retriable_status_before_trailers.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -24435,6 +24491,7 @@ add_executable(retry_non_retriable_status_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_non_retriable_status.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -24497,6 +24554,7 @@ add_executable(retry_per_attempt_recv_timeout_on_last_attempt_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_per_attempt_recv_timeout_on_last_attempt.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -24559,6 +24617,7 @@ add_executable(retry_per_attempt_recv_timeout_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_per_attempt_recv_timeout.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -24621,6 +24680,7 @@ add_executable(retry_recv_initial_metadata_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_recv_initial_metadata.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -24683,6 +24743,7 @@ add_executable(retry_recv_message_replay_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_recv_message_replay.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -24745,6 +24806,7 @@ add_executable(retry_recv_message_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_recv_message.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -24807,6 +24869,7 @@ add_executable(retry_recv_trailing_metadata_error_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_recv_trailing_metadata_error.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -24869,6 +24932,7 @@ add_executable(retry_send_initial_metadata_refs_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_send_initial_metadata_refs.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -24931,6 +24995,7 @@ add_executable(retry_send_op_fails_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_send_op_fails.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -24993,6 +25058,7 @@ add_executable(retry_send_recv_batch_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_send_recv_batch.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -25055,6 +25121,7 @@ add_executable(retry_server_pushback_delay_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_server_pushback_delay.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -25117,6 +25184,7 @@ add_executable(retry_server_pushback_disabled_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_server_pushback_disabled.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -25221,6 +25289,7 @@ add_executable(retry_streaming_after_commit_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_streaming_after_commit.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -25283,6 +25352,7 @@ add_executable(retry_streaming_succeeds_before_replay_finished_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_streaming_succeeds_before_replay_finished.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -25345,6 +25415,7 @@ add_executable(retry_streaming_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_streaming.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -25407,6 +25478,7 @@ add_executable(retry_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -25511,6 +25583,7 @@ add_executable(retry_throttled_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_throttled.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -25573,6 +25646,7 @@ add_executable(retry_too_many_attempts_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_too_many_attempts.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -25635,6 +25709,7 @@ add_executable(retry_transparent_goaway_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_transparent_goaway.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -25697,6 +25772,7 @@ add_executable(retry_transparent_max_concurrent_streams_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_transparent_max_concurrent_streams.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -25759,6 +25835,7 @@ add_executable(retry_transparent_not_sent_on_wire_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_transparent_not_sent_on_wire.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -25821,6 +25898,7 @@ add_executable(retry_unref_before_finish_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_unref_before_finish.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -25883,6 +25961,7 @@ add_executable(retry_unref_before_recv_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/retry_unref_before_recv.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -26866,6 +26945,7 @@ add_executable(server_finishes_request_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/server_finishes_request.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -27149,6 +27229,7 @@ add_executable(server_streaming_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/server_streaming.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -27410,6 +27491,7 @@ add_executable(shutdown_finishes_calls_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/shutdown_finishes_calls.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -27472,6 +27554,7 @@ add_executable(shutdown_finishes_tags_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/shutdown_finishes_tags.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -27597,6 +27680,7 @@ add_executable(simple_delayed_request_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/simple_delayed_request.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -27659,6 +27743,7 @@ add_executable(simple_metadata_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/simple_metadata.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -27765,6 +27850,7 @@ add_executable(simple_request_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/simple_request.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -28690,6 +28776,7 @@ add_executable(streaming_error_response_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/streaming_error_response.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -29421,6 +29508,7 @@ add_executable(test_core_end2end_channelz_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/channelz.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -30679,6 +30767,7 @@ add_executable(timeout_before_request_call_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/timeout_before_request_call.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -31182,6 +31271,7 @@ add_executable(trailing_metadata_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/trailing_metadata.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -32417,6 +32507,7 @@ add_executable(write_buffering_at_end_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/write_buffering_at_end.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)
@ -32479,6 +32570,7 @@ add_executable(write_buffering_test
test/core/end2end/fixtures/proxy.cc
test/core/end2end/tests/write_buffering.cc
test/core/event_engine/event_engine_test_utils.cc
test/core/util/fake_stats_plugin.cc
test/core/util/test_lb_policies.cc
)
if(WIN32 AND MSVC)

1
Package.swift generated
View File

@ -1160,6 +1160,7 @@ let package = Package(
"src/core/lib/channel/promise_based_filter.cc",
"src/core/lib/channel/promise_based_filter.h",
"src/core/lib/channel/server_call_tracer_filter.cc",
"src/core/lib/channel/server_call_tracer_filter.h",
"src/core/lib/channel/status_util.cc",
"src/core/lib/channel/status_util.h",
"src/core/lib/channel/tcp_tracer.h",

196
build_autogenerated.yaml generated

File diff suppressed because it is too large Load Diff

2
gRPC-C++.podspec generated
View File

@ -909,6 +909,7 @@ Pod::Spec.new do |s|
'src/core/lib/channel/context.h',
'src/core/lib/channel/metrics.h',
'src/core/lib/channel/promise_based_filter.h',
'src/core/lib/channel/server_call_tracer_filter.h',
'src/core/lib/channel/status_util.h',
'src/core/lib/channel/tcp_tracer.h',
'src/core/lib/compression/compression_internal.h',
@ -2175,6 +2176,7 @@ Pod::Spec.new do |s|
'src/core/lib/channel/context.h',
'src/core/lib/channel/metrics.h',
'src/core/lib/channel/promise_based_filter.h',
'src/core/lib/channel/server_call_tracer_filter.h',
'src/core/lib/channel/status_util.h',
'src/core/lib/channel/tcp_tracer.h',
'src/core/lib/compression/compression_internal.h',

2
gRPC-Core.podspec generated
View File

@ -1276,6 +1276,7 @@ Pod::Spec.new do |s|
'src/core/lib/channel/promise_based_filter.cc',
'src/core/lib/channel/promise_based_filter.h',
'src/core/lib/channel/server_call_tracer_filter.cc',
'src/core/lib/channel/server_call_tracer_filter.h',
'src/core/lib/channel/status_util.cc',
'src/core/lib/channel/status_util.h',
'src/core/lib/channel/tcp_tracer.h',
@ -2957,6 +2958,7 @@ Pod::Spec.new do |s|
'src/core/lib/channel/context.h',
'src/core/lib/channel/metrics.h',
'src/core/lib/channel/promise_based_filter.h',
'src/core/lib/channel/server_call_tracer_filter.h',
'src/core/lib/channel/status_util.h',
'src/core/lib/channel/tcp_tracer.h',
'src/core/lib/compression/compression_internal.h',

1
grpc.gemspec generated
View File

@ -1166,6 +1166,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/channel/promise_based_filter.cc )
s.files += %w( src/core/lib/channel/promise_based_filter.h )
s.files += %w( src/core/lib/channel/server_call_tracer_filter.cc )
s.files += %w( src/core/lib/channel/server_call_tracer_filter.h )
s.files += %w( src/core/lib/channel/status_util.cc )
s.files += %w( src/core/lib/channel/status_util.h )
s.files += %w( src/core/lib/channel/tcp_tracer.h )

View File

@ -106,6 +106,9 @@ class OpenTelemetryPluginBuilder {
/// options can be added.
OpenTelemetryPluginBuilder& AddPluginOption(
std::unique_ptr<OpenTelemetryPluginOption> option);
// Records \a optional_label_key on all metrics that provide it.
OpenTelemetryPluginBuilder& AddOptionalLabel(
absl::string_view optional_label_key);
/// Registers a global plugin that acts on all channels and servers running on
/// the process.
absl::Status BuildAndRegisterGlobal();

1
package.xml generated
View File

@ -1148,6 +1148,7 @@
<file baseinstalldir="/" name="src/core/lib/channel/promise_based_filter.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/promise_based_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/server_call_tracer_filter.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/server_call_tracer_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/status_util.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/status_util.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/tcp_tracer.h" role="src" />

View File

@ -119,6 +119,9 @@ grpc_cc_library(
srcs = [
"lib/channel/server_call_tracer_filter.cc",
],
hdrs = [
"lib/channel/server_call_tracer_filter.h",
],
external_deps = [
"absl/status",
"absl/status:statusor",
@ -7548,6 +7551,7 @@ grpc_cc_library(
"//:api_trace",
"//:channel",
"//:channel_create",
"//:config",
"//:debug_location",
"//:exec_ctx",
"//:gpr",
@ -7579,10 +7583,14 @@ grpc_cc_library(
],
language = "c++",
deps = [
"arena",
"channel_args",
"no_destruct",
"slice",
"time",
"//:call_tracer",
"//:gpr",
"//:legacy_context",
],
)

View File

@ -1340,6 +1340,7 @@ ClientChannelFilter::CreateLoadBalancedCall(
const grpc_call_element_args& args, grpc_polling_entity* pollent,
grpc_closure* on_call_destruction_complete,
absl::AnyInvocable<void()> on_commit, bool is_transparent_retry) {
promise_detail::Context<Arena> arena_ctx(args.arena);
return OrphanablePtr<FilterBasedLoadBalancedCall>(
args.arena->New<FilterBasedLoadBalancedCall>(
this, args, pollent, on_call_destruction_complete,

View File

@ -33,6 +33,7 @@
#include "src/core/ext/transport/chaotic_good/frame_header.h"
#include "src/core/ext/transport/chaotic_good/settings_metadata.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/config/core_configuration.h"
#include "src/core/lib/event_engine/channel_args_endpoint_config.h"
#include "src/core/lib/event_engine/extensions/chaotic_good_extension.h"
#include "src/core/lib/event_engine/query_extensions.h"

View File

@ -22,6 +22,7 @@
#include <grpc/support/log.h>
#include "src/core/ext/transport/inproc/legacy_inproc_transport.h"
#include "src/core/lib/config/core_configuration.h"
#include "src/core/lib/experiments/experiments.h"
#include "src/core/lib/gprpp/crash.h"
#include "src/core/lib/promise/promise.h"

View File

@ -268,7 +268,7 @@ namespace {
GlobalStatsPluginRegistry::StatsPluginGroup GetStatsPluginGroupForKey(
absl::string_view key) {
if (key == GrpcXdsClient::kServerKey) {
return GlobalStatsPluginRegistry::GetAllStatsPlugins();
return GlobalStatsPluginRegistry::GetStatsPluginsForServer(ChannelArgs{});
}
// TODO(roth): How do we set the authority here?
StatsPlugin::ChannelScope scope(key, "");

View File

@ -32,7 +32,6 @@
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/context.h"
#include "src/core/lib/channel/tcp_tracer.h"
#include "src/core/lib/config/core_configuration.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/slice/slice_buffer.h"
@ -207,8 +206,6 @@ class ServerCallTracerFactory {
static absl::string_view ChannelArgName();
};
void RegisterServerCallTracerFilter(CoreConfiguration::Builder* builder);
// Convenience functions to add call tracers to a call context. Allows setting
// multiple call tracers to a single call. It is only valid to add client call
// tracers before the client_channel filter sees the send_initial_metadata op.

View File

@ -16,7 +16,7 @@
#include "src/core/lib/channel/metrics.h"
#include "absl/container/flat_hash_map.h"
#include <memory>
#include "src/core/lib/gprpp/crash.h"
@ -24,11 +24,10 @@ namespace grpc_core {
// Uses the Construct-on-First-Use idiom to avoid the static initialization
// order fiasco.
absl::flat_hash_map<absl::string_view,
GlobalInstrumentsRegistry::GlobalInstrumentDescriptor>&
std::vector<GlobalInstrumentsRegistry::GlobalInstrumentDescriptor>&
GlobalInstrumentsRegistry::GetInstrumentList() {
static NoDestruct<absl::flat_hash_map<
absl::string_view, GlobalInstrumentsRegistry::GlobalInstrumentDescriptor>>
static NoDestruct<
std::vector<GlobalInstrumentsRegistry::GlobalInstrumentDescriptor>>
instruments;
return *instruments;
}
@ -40,8 +39,11 @@ GlobalInstrumentsRegistry::RegisterUInt64Counter(
absl::Span<const absl::string_view> optional_label_keys,
bool enable_by_default) {
auto& instruments = GetInstrumentList();
if (instruments.find(name) != instruments.end()) {
Crash(absl::StrFormat("Metric name %s has already been registered.", name));
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());
@ -56,7 +58,7 @@ GlobalInstrumentsRegistry::RegisterUInt64Counter(
descriptor.label_keys = {label_keys.begin(), label_keys.end()};
descriptor.optional_label_keys = {optional_label_keys.begin(),
optional_label_keys.end()};
instruments.emplace(name, std::move(descriptor));
instruments.push_back(std::move(descriptor));
GlobalUInt64CounterHandle handle;
handle.index = index;
return handle;
@ -69,8 +71,11 @@ GlobalInstrumentsRegistry::RegisterDoubleCounter(
absl::Span<const absl::string_view> optional_label_keys,
bool enable_by_default) {
auto& instruments = GetInstrumentList();
if (instruments.find(name) != instruments.end()) {
Crash(absl::StrFormat("Metric name %s has already been registered.", name));
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());
@ -85,7 +90,7 @@ GlobalInstrumentsRegistry::RegisterDoubleCounter(
descriptor.label_keys = {label_keys.begin(), label_keys.end()};
descriptor.optional_label_keys = {optional_label_keys.begin(),
optional_label_keys.end()};
instruments.emplace(name, std::move(descriptor));
instruments.push_back(std::move(descriptor));
GlobalDoubleCounterHandle handle;
handle.index = index;
return handle;
@ -98,8 +103,11 @@ GlobalInstrumentsRegistry::RegisterUInt64Histogram(
absl::Span<const absl::string_view> optional_label_keys,
bool enable_by_default) {
auto& instruments = GetInstrumentList();
if (instruments.find(name) != instruments.end()) {
Crash(absl::StrFormat("Metric name %s has already been registered.", name));
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());
@ -114,7 +122,7 @@ GlobalInstrumentsRegistry::RegisterUInt64Histogram(
descriptor.label_keys = {label_keys.begin(), label_keys.end()};
descriptor.optional_label_keys = {optional_label_keys.begin(),
optional_label_keys.end()};
instruments.emplace(name, std::move(descriptor));
instruments.push_back(std::move(descriptor));
GlobalUInt64HistogramHandle handle;
handle.index = index;
return handle;
@ -127,8 +135,11 @@ GlobalInstrumentsRegistry::RegisterDoubleHistogram(
absl::Span<const absl::string_view> optional_label_keys,
bool enable_by_default) {
auto& instruments = GetInstrumentList();
if (instruments.find(name) != instruments.end()) {
Crash(absl::StrFormat("Metric name %s has already been registered.", name));
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());
@ -143,7 +154,7 @@ GlobalInstrumentsRegistry::RegisterDoubleHistogram(
descriptor.label_keys = {label_keys.begin(), label_keys.end()};
descriptor.optional_label_keys = {optional_label_keys.begin(),
optional_label_keys.end()};
instruments.emplace(name, std::move(descriptor));
instruments.push_back(std::move(descriptor));
GlobalDoubleHistogramHandle handle;
handle.index = index;
return handle;
@ -156,8 +167,11 @@ GlobalInstrumentsRegistry::RegisterInt64Gauge(
absl::Span<const absl::string_view> optional_label_keys,
bool enable_by_default) {
auto& instruments = GetInstrumentList();
if (instruments.find(name) != instruments.end()) {
Crash(absl::StrFormat("Metric name %s has already been registered.", name));
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());
@ -172,7 +186,7 @@ GlobalInstrumentsRegistry::RegisterInt64Gauge(
descriptor.label_keys = {label_keys.begin(), label_keys.end()};
descriptor.optional_label_keys = {optional_label_keys.begin(),
optional_label_keys.end()};
instruments.emplace(name, std::move(descriptor));
instruments.push_back(std::move(descriptor));
GlobalInt64GaugeHandle handle;
handle.index = index;
return handle;
@ -185,8 +199,11 @@ GlobalInstrumentsRegistry::RegisterDoubleGauge(
absl::Span<const absl::string_view> optional_label_keys,
bool enable_by_default) {
auto& instruments = GetInstrumentList();
if (instruments.find(name) != instruments.end()) {
Crash(absl::StrFormat("Metric name %s has already been registered.", name));
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());
@ -201,7 +218,7 @@ GlobalInstrumentsRegistry::RegisterDoubleGauge(
descriptor.label_keys = {label_keys.begin(), label_keys.end()};
descriptor.optional_label_keys = {optional_label_keys.begin(),
optional_label_keys.end()};
instruments.emplace(name, std::move(descriptor));
instruments.push_back(std::move(descriptor));
GlobalDoubleGaugeHandle handle;
handle.index = index;
return handle;
@ -214,8 +231,11 @@ GlobalInstrumentsRegistry::RegisterCallbackInt64Gauge(
absl::Span<const absl::string_view> optional_label_keys,
bool enable_by_default) {
auto& instruments = GetInstrumentList();
if (instruments.find(name) != instruments.end()) {
Crash(absl::StrFormat("Metric name %s has already been registered.", name));
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());
@ -230,7 +250,7 @@ GlobalInstrumentsRegistry::RegisterCallbackInt64Gauge(
descriptor.label_keys = {label_keys.begin(), label_keys.end()};
descriptor.optional_label_keys = {optional_label_keys.begin(),
optional_label_keys.end()};
instruments.emplace(name, std::move(descriptor));
instruments.push_back(std::move(descriptor));
GlobalCallbackInt64GaugeHandle handle;
handle.index = index;
return handle;
@ -243,8 +263,11 @@ GlobalInstrumentsRegistry::RegisterCallbackDoubleGauge(
absl::Span<const absl::string_view> optional_label_keys,
bool enable_by_default) {
auto& instruments = GetInstrumentList();
if (instruments.find(name) != instruments.end()) {
Crash(absl::StrFormat("Metric name %s has already been registered.", name));
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());
@ -259,7 +282,7 @@ GlobalInstrumentsRegistry::RegisterCallbackDoubleGauge(
descriptor.label_keys = {label_keys.begin(), label_keys.end()};
descriptor.optional_label_keys = {optional_label_keys.begin(),
optional_label_keys.end()};
instruments.emplace(name, std::move(descriptor));
instruments.push_back(std::move(descriptor));
GlobalCallbackDoubleGaugeHandle handle;
handle.index = index;
return handle;
@ -268,10 +291,16 @@ GlobalInstrumentsRegistry::RegisterCallbackDoubleGauge(
void GlobalInstrumentsRegistry::ForEach(
absl::FunctionRef<void(const GlobalInstrumentDescriptor&)> f) {
for (const auto& instrument : GetInstrumentList()) {
f(instrument.second);
f(instrument);
}
}
const GlobalInstrumentsRegistry::GlobalInstrumentDescriptor&
GlobalInstrumentsRegistry::GetInstrumentDescriptor(
GlobalInstrumentHandle handle) {
return GetInstrumentList().at(handle.index);
}
RegisteredMetricCallback::RegisteredMetricCallback(
GlobalStatsPluginRegistry::StatsPluginGroup& stats_plugin_group,
absl::AnyInvocable<void(CallbackMetricReporter&)> callback,
@ -281,14 +310,14 @@ RegisteredMetricCallback::RegisteredMetricCallback(
callback_(std::move(callback)),
metrics_(std::move(metrics)),
min_interval_(min_interval) {
for (auto& plugin : stats_plugin_group_.plugins_) {
plugin->AddCallback(this);
for (auto& state : stats_plugin_group_.plugins_state_) {
state.plugin->AddCallback(this);
}
}
RegisteredMetricCallback::~RegisteredMetricCallback() {
for (auto& plugin : stats_plugin_group_.plugins_) {
plugin->RemoveCallback(this);
for (auto& state : stats_plugin_group_.plugins_state_) {
state.plugin->RemoveCallback(this);
}
}
@ -301,6 +330,28 @@ GlobalStatsPluginRegistry::StatsPluginGroup::RegisterCallback(
*this, std::move(callback), std::move(metrics), min_interval);
}
void GlobalStatsPluginRegistry::StatsPluginGroup::AddClientCallTracers(
const Slice& path, bool registered_method,
grpc_call_context_element* call_context) {
for (auto& state : plugins_state_) {
auto* call_tracer = state.plugin->GetClientCallTracer(
path, registered_method, state.scope_config);
if (call_tracer != nullptr) {
AddClientCallTracerToContext(call_context, call_tracer);
}
}
}
void GlobalStatsPluginRegistry::StatsPluginGroup::AddServerCallTracers(
grpc_call_context_element* call_context) {
for (auto& state : plugins_state_) {
auto* call_tracer = state.plugin->GetServerCallTracer(state.scope_config);
if (call_tracer != nullptr) {
AddServerCallTracerToContext(call_context, call_tracer);
}
}
}
NoDestruct<Mutex> GlobalStatsPluginRegistry::mutex_;
NoDestruct<std::vector<std::shared_ptr<StatsPlugin>>>
GlobalStatsPluginRegistry::plugins_;
@ -311,24 +362,32 @@ void GlobalStatsPluginRegistry::RegisterStatsPlugin(
plugins_->push_back(std::move(plugin));
}
GlobalStatsPluginRegistry::StatsPluginGroup
GlobalStatsPluginRegistry::GetAllStatsPlugins() {
MutexLock lock(&*mutex_);
StatsPluginGroup group;
for (const auto& plugin : *plugins_) {
group.push_back(plugin);
}
return group;
}
GlobalStatsPluginRegistry::StatsPluginGroup
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
const StatsPlugin::ChannelScope& scope) {
MutexLock lock(&*mutex_);
StatsPluginGroup group;
for (const auto& plugin : *plugins_) {
if (plugin->IsEnabledForChannel(scope)) {
group.push_back(plugin);
bool is_enabled = false;
std::shared_ptr<StatsPlugin::ScopeConfig> config;
std::tie(is_enabled, config) = plugin->IsEnabledForChannel(scope);
if (is_enabled) {
group.AddStatsPlugin(plugin, std::move(config));
}
}
return group;
}
GlobalStatsPluginRegistry::StatsPluginGroup
GlobalStatsPluginRegistry::GetStatsPluginsForServer(const ChannelArgs& args) {
MutexLock lock(&*mutex_);
StatsPluginGroup group;
for (const auto& plugin : *plugins_) {
bool is_enabled = false;
std::shared_ptr<StatsPlugin::ScopeConfig> config;
std::tie(is_enabled, config) = plugin->IsEnabledForServer(args);
if (is_enabled) {
group.AddStatsPlugin(plugin, std::move(config));
}
}
return group;

View File

@ -29,10 +29,13 @@
#include <grpc/support/log.h>
#include "src/core/lib/channel/call_tracer.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/context.h"
#include "src/core/lib/gprpp/no_destruct.h"
#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/gprpp/time.h"
#include "src/core/lib/slice/slice.h"
namespace grpc_core {
@ -58,10 +61,11 @@ class GlobalInstrumentsRegistry {
kGauge,
kCallbackGauge,
};
using InstrumentID = uint32_t;
struct GlobalInstrumentDescriptor {
ValueType value_type;
InstrumentType instrument_type;
uint32_t index;
InstrumentID index;
bool enable_by_default;
absl::string_view name;
absl::string_view description;
@ -69,20 +73,20 @@ class GlobalInstrumentsRegistry {
std::vector<absl::string_view> label_keys;
std::vector<absl::string_view> optional_label_keys;
};
struct GlobalHandle {
struct GlobalInstrumentHandle {
// This is the index for the corresponding registered instrument that
// StatsPlugins can use to uniquely identify an instrument in the current
// process. Though this is not guaranteed to be stable between different
// runs or between different versions.
uint32_t index;
InstrumentID index;
};
struct GlobalUInt64CounterHandle : public GlobalHandle {};
struct GlobalDoubleCounterHandle : public GlobalHandle {};
struct GlobalUInt64HistogramHandle : public GlobalHandle {};
struct GlobalDoubleHistogramHandle : public GlobalHandle {};
struct GlobalInt64GaugeHandle : public GlobalHandle {};
struct GlobalDoubleGaugeHandle : public GlobalHandle {};
struct GlobalCallbackHandle : public GlobalHandle {};
struct GlobalUInt64CounterHandle : public GlobalInstrumentHandle {};
struct GlobalDoubleCounterHandle : public GlobalInstrumentHandle {};
struct GlobalUInt64HistogramHandle : public GlobalInstrumentHandle {};
struct GlobalDoubleHistogramHandle : public GlobalInstrumentHandle {};
struct GlobalInt64GaugeHandle : public GlobalInstrumentHandle {};
struct GlobalDoubleGaugeHandle : public GlobalInstrumentHandle {};
struct GlobalCallbackHandle : public GlobalInstrumentHandle {};
struct GlobalCallbackInt64GaugeHandle : public GlobalCallbackHandle {};
struct GlobalCallbackDoubleGaugeHandle : public GlobalCallbackHandle {};
@ -130,14 +134,15 @@ class GlobalInstrumentsRegistry {
static void ForEach(
absl::FunctionRef<void(const GlobalInstrumentDescriptor&)> f);
static const GlobalInstrumentDescriptor& GetInstrumentDescriptor(
GlobalInstrumentHandle handle);
private:
friend class GlobalInstrumentsRegistryTestPeer;
GlobalInstrumentsRegistry() = delete;
static absl::flat_hash_map<
absl::string_view, GlobalInstrumentsRegistry::GlobalInstrumentDescriptor>&
static std::vector<GlobalInstrumentsRegistry::GlobalInstrumentDescriptor>&
GetInstrumentList();
};
@ -162,6 +167,7 @@ class RegisteredMetricCallback;
// The StatsPlugin interface.
class StatsPlugin {
public:
// Configuration (scope) for a specific client channel.
class ChannelScope {
public:
ChannelScope(absl::string_view target, absl::string_view authority)
@ -174,37 +180,74 @@ class StatsPlugin {
absl::string_view target_;
absl::string_view authority_;
};
// A general-purpose way for stats plugin to store per-channel or per-server
// state.
class ScopeConfig {
public:
virtual ~ScopeConfig() = default;
};
virtual ~StatsPlugin() = default;
virtual bool IsEnabledForChannel(const ChannelScope& scope) const = 0;
virtual bool IsEnabledForServer(const ChannelArgs& args) const = 0;
// Whether this stats plugin is enabled for the channel specified by \a scope.
// Returns true and a channel-specific ScopeConfig which may then be used to
// configure the ClientCallTracer in GetClientCallTracer().
virtual std::pair<bool, std::shared_ptr<ScopeConfig>> IsEnabledForChannel(
const ChannelScope& scope) const = 0;
// Whether this stats plugin is enabled for the server specified by \a args.
// Returns true and a server-specific ScopeConfig which may then be used to
// configure the ServerCallTracer in GetServerCallTracer().
virtual std::pair<bool, std::shared_ptr<ScopeConfig>> IsEnabledForServer(
const ChannelArgs& args) const = 0;
// Adds \a value to the uint64 counter specified by \a handle. \a label_values
// and \a optional_label_values specify attributes that are associated with
// this measurement and must match with their corresponding keys in
// GlobalInstrumentsRegistry::RegisterUInt64Counter().
virtual void AddCounter(
GlobalInstrumentsRegistry::GlobalUInt64CounterHandle handle,
uint64_t value, absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) = 0;
absl::Span<const absl::string_view> optional_label_values) = 0;
// Adds \a value to the double counter specified by \a handle. \a label_values
// and \a optional_label_values specify attributes that are associated with
// this measurement and must match with their corresponding keys in
// GlobalInstrumentsRegistry::RegisterDoubleCounter().
virtual void AddCounter(
GlobalInstrumentsRegistry::GlobalDoubleCounterHandle handle, double value,
absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) = 0;
absl::Span<const absl::string_view> optional_label_values) = 0;
// Records a uint64 \a value to the histogram specified by \a handle. \a
// label_values and \a optional_label_values specify attributes that are
// associated with this measurement and must match with their corresponding
// keys in GlobalInstrumentsRegistry::RegisterUInt64Histogram().
virtual void RecordHistogram(
GlobalInstrumentsRegistry::GlobalUInt64HistogramHandle handle,
uint64_t value, absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) = 0;
absl::Span<const absl::string_view> optional_label_values) = 0;
// Records a double \a value to the histogram specified by \a handle. \a
// label_values and \a optional_label_values specify attributes that are
// associated with this measurement and must match with their corresponding
// keys in GlobalInstrumentsRegistry::RegisterDoubleHistogram().
virtual void RecordHistogram(
GlobalInstrumentsRegistry::GlobalDoubleHistogramHandle handle,
double value, absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) = 0;
absl::Span<const absl::string_view> optional_label_values) = 0;
// Sets an int64 \a value to the gauge specifed by \a handle. \a
// label_values and \a optional_label_values specify attributes that are
// associated with this measurement and must match with their corresponding
// keys in GlobalInstrumentsRegistry::RegisterInt64Gauge().
virtual void SetGauge(
GlobalInstrumentsRegistry::GlobalInt64GaugeHandle handle, int64_t value,
absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) = 0;
absl::Span<const absl::string_view> optional_label_values) = 0;
// Sets a double \a value to the gauge specifed by \a handle. \a
// label_values and \a optional_label_values specify attributes that are
// associated with this measurement and must match with their corresponding
// keys in GlobalInstrumentsRegistry::RegisterDoubleGauge().
virtual void SetGauge(
GlobalInstrumentsRegistry::GlobalDoubleGaugeHandle handle, double value,
absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) = 0;
absl::Span<const absl::string_view> optional_label_values) = 0;
// Adds a callback to be invoked when the stats plugin wants to
// populate the corresponding metrics (see callback->metrics() for list).
virtual void AddCallback(RegisteredMetricCallback* callback) = 0;
@ -212,13 +255,15 @@ class StatsPlugin {
// plugin may not use the callback after this method returns.
virtual void RemoveCallback(RegisteredMetricCallback* callback) = 0;
// TODO(yijiem): Details pending.
// std::unique_ptr<AsyncInstrument> GetObservableGauge(
// absl::string_view name, absl::string_view description,
// absl::string_view unit);
// AsyncInstrument* GetObservableCounter(
// absl::string_view name, absl::string_view description,
// absl::string_view unit);
// Gets a ClientCallTracer associated with this stats plugin which can be used
// in a call.
virtual ClientCallTracer* GetClientCallTracer(
const Slice& path, bool registered_method,
std::shared_ptr<ScopeConfig> scope_config) = 0;
// Gets a ServerCallTracer associated with this stats plugin which can be used
// in a call.
virtual ServerCallTracer* GetServerCallTracer(
std::shared_ptr<ScopeConfig> scope_config) = 0;
// TODO(yijiem): This is an optimization for the StatsPlugin to create its own
// representation of the label_values and use it multiple times. We would
@ -230,63 +275,55 @@ class StatsPlugin {
// absl::Span<absl::string_view> label_values) = 0;
};
// A global registry of StatsPlugins. It has shared ownership to the registered
// StatsPlugins. This API is supposed to be used during runtime after the main
// A global registry of stats plugins. It has shared ownership to the registered
// stats plugins. This API is supposed to be used during runtime after the main
// function begins. This API is thread-safe.
class GlobalStatsPluginRegistry {
public:
// A stats plugin group object is how the code in gRPC normally interacts with
// stats plugins. They got a stats plugin group which contains all the stats
// plugins for a specific scope and all operations on the stats plugin group
// will be applied to all the stats plugins within the group.
class StatsPluginGroup {
public:
void push_back(std::shared_ptr<StatsPlugin> plugin) {
plugins_.push_back(std::move(plugin));
// Adds a stats plugin and a scope config (per-channel or per-server) to the
// group.
void AddStatsPlugin(std::shared_ptr<StatsPlugin> plugin,
std::shared_ptr<StatsPlugin::ScopeConfig> config) {
PluginState plugin_state;
plugin_state.plugin = std::move(plugin);
plugin_state.scope_config = std::move(config);
plugins_state_.push_back(std::move(plugin_state));
}
void AddCounter(GlobalInstrumentsRegistry::GlobalUInt64CounterHandle handle,
uint64_t value,
// 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) {
for (auto& plugin : plugins_) {
plugin->AddCounter(handle, value, label_values, optional_values);
for (auto& state : plugins_state_) {
state.plugin->AddCounter(handle, value, label_values, optional_values);
}
}
void AddCounter(GlobalInstrumentsRegistry::GlobalDoubleCounterHandle handle,
double value,
absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) {
for (auto& plugin : plugins_) {
plugin->AddCounter(handle, value, label_values, optional_values);
// Records a value to a histogram in all stats plugins within the group. See
// the StatsPlugin interface for more documentation and valid types.
template <class HandleType, class ValueType>
void RecordHistogram(HandleType handle, ValueType value,
absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) {
for (auto& state : plugins_state_) {
state.plugin->RecordHistogram(handle, value, label_values,
optional_values);
}
}
void RecordHistogram(
GlobalInstrumentsRegistry::GlobalUInt64HistogramHandle handle,
uint64_t value, absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) {
for (auto& plugin : plugins_) {
plugin->RecordHistogram(handle, value, label_values, optional_values);
}
}
void RecordHistogram(
GlobalInstrumentsRegistry::GlobalDoubleHistogramHandle handle,
double value, absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) {
for (auto& plugin : plugins_) {
plugin->RecordHistogram(handle, value, label_values, optional_values);
}
}
void SetGauge(GlobalInstrumentsRegistry::GlobalInt64GaugeHandle handle,
int64_t value,
// Sets a value to a gauge in all stats plugins within the group. See the
// StatsPlugin interface for more documentation and valid types.
template <class HandleType, class ValueType>
void SetGauge(HandleType handle, ValueType value,
absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) {
for (auto& plugin : plugins_) {
plugin->SetGauge(handle, value, label_values, optional_values);
}
}
void SetGauge(GlobalInstrumentsRegistry::GlobalDoubleGaugeHandle handle,
double value,
absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) {
for (auto& plugin : plugins_) {
plugin->SetGauge(handle, value, label_values, optional_values);
for (auto& state : plugins_state_) {
state.plugin->SetGauge(handle, value, label_values, optional_values);
}
}
@ -303,21 +340,33 @@ class GlobalStatsPluginRegistry {
std::vector<GlobalInstrumentsRegistry::GlobalCallbackHandle> metrics,
Duration min_interval = Duration::Seconds(5));
// Adds all available client call tracers associated with the stats plugins
// within the group to \a call_context.
void AddClientCallTracers(const Slice& path, bool registered_method,
grpc_call_context_element* call_context);
// Adds all available server call tracers associated with the stats plugins
// within the group to \a call_context.
void AddServerCallTracers(grpc_call_context_element* call_context);
private:
friend class RegisteredMetricCallback;
std::vector<std::shared_ptr<StatsPlugin>> plugins_;
struct PluginState {
std::shared_ptr<StatsPlugin::ScopeConfig> scope_config;
std::shared_ptr<StatsPlugin> plugin;
};
std::vector<PluginState> plugins_state_;
};
// Registers a stats plugin with the global stats plugin registry.
static void RegisterStatsPlugin(std::shared_ptr<StatsPlugin> plugin);
// The following functions can be invoked to get a StatsPluginGroup for
// a specified scope.
static StatsPluginGroup GetAllStatsPlugins();
static StatsPluginGroup GetStatsPluginsForChannel(
const StatsPlugin::ChannelScope& scope);
// TODO(yijiem): Implement this.
// StatsPluginsGroup GetStatsPluginsForServer(ChannelArgs& args);
static StatsPluginGroup GetStatsPluginsForServer(const ChannelArgs& args);
private:
friend class GlobalStatsPluginRegistryTestPeer;

View File

@ -16,6 +16,8 @@
#include <grpc/support/port_platform.h>
#include "src/core/lib/channel/server_call_tracer_filter.h"
#include <functional>
#include <utility>

View File

@ -0,0 +1,28 @@
// Copyright 2024 The 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.
#ifndef GRPC_SRC_CORE_LIB_CHANNEL_SERVER_CALL_TRACER_FILTER_H
#define GRPC_SRC_CORE_LIB_CHANNEL_SERVER_CALL_TRACER_FILTER_H
#include <grpc/support/port_platform.h>
#include "src/core/lib/config/core_configuration.h"
namespace grpc_core {
void RegisterServerCallTracerFilter(CoreConfiguration::Builder* builder);
} // namespace grpc_core
#endif // GRPC_SRC_CORE_LIB_CHANNEL_SERVER_CALL_TRACER_FILTER_H

View File

@ -588,6 +588,12 @@ class FilterStackCall final : public Call {
}
private:
class ScopedContext : public promise_detail::Context<Arena> {
public:
explicit ScopedContext(FilterStackCall* call)
: promise_detail::Context<Arena>(call->arena()) {}
};
static constexpr gpr_atm kRecvNone = 0;
static constexpr gpr_atm kRecvInitialMetadataFirst = 1;
@ -807,6 +813,7 @@ grpc_error_handle FilterStackCall::Create(grpc_call_create_args* args,
GPR_DEBUG_ASSERT(FromCallStack(call->call_stack()) == call);
*out_call = call->c_ptr();
grpc_slice path = grpc_empty_slice();
ScopedContext ctx(call);
if (call->is_client()) {
call->final_op_.client.status_details = nullptr;
call->final_op_.client.status = nullptr;
@ -822,6 +829,8 @@ grpc_error_handle FilterStackCall::Create(grpc_call_create_args* args,
call->send_initial_metadata_.Set(
GrpcRegisteredMethod(), reinterpret_cast<void*>(static_cast<uintptr_t>(
args->registered_method)));
channel_stack->stats_plugin_group->AddClientCallTracers(
Slice(CSliceRef(path)), args->registered_method, call->context_);
} else {
global_stats().IncrementServerCallsCreated();
call->final_op_.server.cancelled = nullptr;
@ -830,6 +839,9 @@ grpc_error_handle FilterStackCall::Create(grpc_call_create_args* args,
// collecting from when the call is created at the transport. The idea is
// that the transport would create the call tracer and pass it in as part of
// the metadata.
// TODO(yijiem): OpenCensus and internal Census is still using this way to
// set server call tracer. We need to refactor them to stats plugins
// (including removing the client channel filters).
if (args->server != nullptr &&
args->server->server_call_tracer_factory() != nullptr) {
auto* server_call_tracer =
@ -846,6 +858,7 @@ grpc_error_handle FilterStackCall::Create(grpc_call_create_args* args,
call->ContextSet(GRPC_CONTEXT_CALL_TRACER, server_call_tracer, nullptr);
}
}
channel_stack->stats_plugin_group->AddServerCallTracers(call->context_);
}
Call* parent = Call::FromC(args->parent);
@ -2725,6 +2738,8 @@ class ClientPromiseBasedCall final : public PromiseBasedCall {
"non-nullptr.");
}
ScopedContext context(this);
args->channel->channel_stack()->stats_plugin_group->AddClientCallTracers(
*args->path, args->registered_method, this->context());
send_initial_metadata_ =
GetContext<Arena>()->MakePooled<ClientMetadata>(GetContext<Arena>());
send_initial_metadata_->Set(HttpPathMetadata(), std::move(*args->path));
@ -3390,11 +3405,16 @@ ServerPromiseBasedCall::ServerPromiseBasedCall(Arena* arena,
if (channelz_node != nullptr) {
channelz_node->RecordCallStarted();
}
ScopedContext activity_context(this);
// TODO(yashykt): In the future, we want to also enable stats and trace
// collecting from when the call is created at the transport. The idea is that
// the transport would create the call tracer and pass it in as part of the
// metadata.
if (args->server->server_call_tracer_factory() != nullptr) {
// TODO(yijiem): OpenCensus and internal Census is still using this way to
// set server call tracer. We need to refactor them to stats plugins
// (including removing the client channel filters).
if (args->server != nullptr &&
args->server->server_call_tracer_factory() != nullptr) {
auto* server_call_tracer =
args->server->server_call_tracer_factory()->CreateNewServerCallTracer(
arena, args->server->channel_args());
@ -3409,7 +3429,8 @@ ServerPromiseBasedCall::ServerPromiseBasedCall(Arena* arena,
ContextSet(GRPC_CONTEXT_CALL_TRACER, server_call_tracer, nullptr);
}
}
ScopedContext activity_context(this);
args->channel->channel_stack()->stats_plugin_group->AddServerCallTracers(
context());
Spawn("server_promise",
channel()->channel_stack()->MakeServerCallPromise(
CallArgs{nullptr, ClientInitialMetadataOutstandingToken::Empty(),

View File

@ -89,12 +89,17 @@ absl::StatusOr<OrphanablePtr<Channel>> LegacyChannel::Create(
status.ToString().c_str());
return status;
}
// TODO(roth): Figure out how to populate authority here.
// Or maybe just don't worry about this if no one needs it until after
// the call v3 stack lands.
StatsPlugin::ChannelScope scope(builder.target(), "");
*(*r)->stats_plugin_group =
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(scope);
if (channel_stack_type == GRPC_SERVER_CHANNEL) {
*(*r)->stats_plugin_group =
GlobalStatsPluginRegistry::GetStatsPluginsForServer(args);
} else {
// TODO(roth): Figure out how to populate authority here.
// Or maybe just don't worry about this if no one needs it until after
// the call v3 stack lands.
StatsPlugin::ChannelScope scope(target, "");
*(*r)->stats_plugin_group =
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(scope);
}
return MakeOrphanable<LegacyChannel>(
grpc_channel_stack_type_is_client(builder.channel_stack_type()),
builder.IsPromising(), std::move(target), args, std::move(*r));

View File

@ -20,6 +20,7 @@
#include <grpc/grpc.h>
#include "src/core/lib/channel/server_call_tracer_filter.h"
#include "src/core/lib/config/core_configuration.h"
#include "src/core/lib/surface/channel_stack_type.h"
#include "src/core/lib/surface/lame_client.h"
@ -27,7 +28,6 @@
#include "src/core/lib/transport/http_connect_handshaker.h"
#include "src/core/lib/transport/tcp_connect_handshaker.h"
namespace grpc_event_engine {
namespace experimental {
extern void RegisterEventEngineChannelArgPreconditioning(

View File

@ -31,14 +31,13 @@ package(
grpc_cc_library(
name = "otel_plugin",
srcs = [
"otel_client_filter.cc",
"otel_client_call_tracer.cc",
"otel_plugin.cc",
"otel_server_call_tracer.cc",
],
hdrs = [
"key_value_iterable.h",
"otel_call_tracer.h",
"otel_client_filter.h",
"otel_client_call_tracer.h",
"otel_plugin.h",
"otel_server_call_tracer.h",
"//:include/grpcpp/ext/otel_plugin.h",
@ -77,6 +76,7 @@ grpc_cc_library(
"//src/core:context",
"//src/core:error",
"//src/core:metadata_batch",
"//src/core:metrics",
"//src/core:slice",
"//src/core:slice_buffer",
],

View File

@ -46,23 +46,26 @@ inline opentelemetry::nostd::string_view AbslStrViewToOpenTelemetryStrView(
// An iterable class based on opentelemetry::common::KeyValueIterable that
// allows gRPC to iterate on its various sources of attributes and avoid an
// allocation in cases wherever possible.
class KeyValueIterable : public opentelemetry::common::KeyValueIterable {
class OpenTelemetryPlugin::KeyValueIterable
: public opentelemetry::common::KeyValueIterable {
public:
explicit KeyValueIterable(
KeyValueIterable(
const std::vector<std::unique_ptr<LabelsIterable>>&
injected_labels_from_plugin_options,
absl::Span<const std::pair<absl::string_view, absl::string_view>>
additional_labels,
const ActivePluginOptionsView* active_plugin_options_view,
const OpenTelemetryPlugin::ActivePluginOptionsView*
active_plugin_options_view,
absl::Span<const std::shared_ptr<std::map<std::string, std::string>>>
optional_labels_span,
bool is_client)
bool is_client, const OpenTelemetryPlugin* otel_plugin)
: injected_labels_from_plugin_options_(
injected_labels_from_plugin_options),
additional_labels_(additional_labels),
active_plugin_options_view_(active_plugin_options_view),
optional_labels_(optional_labels_span),
is_client_(is_client) {}
is_client_(is_client),
otel_plugin_(otel_plugin) {}
bool ForEachKeyValue(opentelemetry::nostd::function_ref<
bool(opentelemetry::nostd::string_view,
@ -75,7 +78,8 @@ class KeyValueIterable : public opentelemetry::common::KeyValueIterable {
size_t /*index*/) {
return plugin_option.labels_injector()->AddOptionalLabels(
is_client_, optional_labels_, callback);
})) {
},
otel_plugin_)) {
return false;
}
for (const auto& plugin_option_injected_iterable :
@ -115,7 +119,8 @@ class KeyValueIterable : public opentelemetry::common::KeyValueIterable {
size += plugin_option.labels_injector()->GetOptionalLabelsSize(
is_client_, optional_labels_);
return true;
});
},
otel_plugin_);
}
return size;
}
@ -125,10 +130,12 @@ class KeyValueIterable : public opentelemetry::common::KeyValueIterable {
injected_labels_from_plugin_options_;
absl::Span<const std::pair<absl::string_view, absl::string_view>>
additional_labels_;
const ActivePluginOptionsView* active_plugin_options_view_;
const OpenTelemetryPlugin::ActivePluginOptionsView*
active_plugin_options_view_;
absl::Span<const std::shared_ptr<std::map<std::string, std::string>>>
optional_labels_;
bool is_client_;
const OpenTelemetryPlugin* otel_plugin_;
};
} // namespace internal

View File

@ -0,0 +1,282 @@
//
//
// 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 <grpc/support/port_platform.h>
#include "src/cpp/ext/otel/otel_client_call_tracer.h"
#include <stdint.h>
#include <array>
#include <functional>
#include <memory>
#include <string>
#include <utility>
#include "absl/functional/any_invocable.h"
#include "absl/status/status.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "absl/types/optional.h"
#include "absl/types/span.h"
#include "opentelemetry/context/context.h"
#include "opentelemetry/metrics/sync_instruments.h"
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include "src/core/client_channel/client_channel_filter.h"
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/channel/context.h"
#include "src/core/lib/channel/status_util.h"
#include "src/core/lib/channel/tcp_tracer.h"
#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/promise/context.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/slice/slice_buffer.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/cpp/ext/otel/key_value_iterable.h"
#include "src/cpp/ext/otel/otel_plugin.h"
namespace grpc {
namespace internal {
//
// OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer
//
OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer::CallAttemptTracer(
const OpenTelemetryPlugin::ClientCallTracer* parent, bool arena_allocated)
: parent_(parent),
arena_allocated_(arena_allocated),
start_time_(absl::Now()) {
if (parent_->otel_plugin_->client_.attempt.started != nullptr) {
std::array<std::pair<absl::string_view, absl::string_view>, 2>
additional_labels = {
{{OpenTelemetryMethodKey(), parent_->MethodForStats()},
{OpenTelemetryTargetKey(),
parent_->scope_config_->filtered_target()}}};
// We might not have all the injected labels that we want at this point, so
// avoid recording a subset of injected labels here.
parent_->otel_plugin_->client_.attempt.started->Add(
1, KeyValueIterable(
/*injected_labels_from_plugin_options=*/{}, additional_labels,
/*active_plugin_options_view=*/nullptr,
/*optional_labels_span=*/{}, /*is_client=*/true,
parent_->otel_plugin_));
}
}
void OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer::
RecordReceivedInitialMetadata(grpc_metadata_batch* recv_initial_metadata) {
parent_->scope_config_->active_plugin_options_view().ForEach(
[&](const InternalOpenTelemetryPluginOption& plugin_option,
size_t /*index*/) {
auto* labels_injector = plugin_option.labels_injector();
if (labels_injector != nullptr) {
injected_labels_from_plugin_options_.push_back(
labels_injector->GetLabels(recv_initial_metadata));
}
return true;
},
parent_->otel_plugin_);
}
void OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer::
RecordSendInitialMetadata(grpc_metadata_batch* send_initial_metadata) {
parent_->scope_config_->active_plugin_options_view().ForEach(
[&](const InternalOpenTelemetryPluginOption& plugin_option,
size_t /*index*/) {
auto* labels_injector = plugin_option.labels_injector();
if (labels_injector != nullptr) {
labels_injector->AddLabels(send_initial_metadata, nullptr);
}
return true;
},
parent_->otel_plugin_);
}
void OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer::
RecordSendMessage(const grpc_core::SliceBuffer& send_message) {
RecordAnnotation(
absl::StrFormat("Send message: %ld bytes", send_message.Length()));
}
void OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer::
RecordSendCompressedMessage(
const grpc_core::SliceBuffer& send_compressed_message) {
RecordAnnotation(absl::StrFormat("Send compressed message: %ld bytes",
send_compressed_message.Length()));
}
void OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer::
RecordReceivedMessage(const grpc_core::SliceBuffer& recv_message) {
RecordAnnotation(
absl::StrFormat("Received message: %ld bytes", recv_message.Length()));
}
void OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer::
RecordReceivedDecompressedMessage(
const grpc_core::SliceBuffer& recv_decompressed_message) {
RecordAnnotation(absl::StrFormat("Received decompressed message: %ld bytes",
recv_decompressed_message.Length()));
}
void OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer::
RecordReceivedTrailingMetadata(
absl::Status status, grpc_metadata_batch* /*recv_trailing_metadata*/,
const grpc_transport_stream_stats* transport_stream_stats) {
std::array<std::pair<absl::string_view, absl::string_view>, 3>
additional_labels = {
{{OpenTelemetryMethodKey(), parent_->MethodForStats()},
{OpenTelemetryTargetKey(),
parent_->scope_config_->filtered_target()},
{OpenTelemetryStatusKey(),
grpc_status_code_to_string(
static_cast<grpc_status_code>(status.code()))}}};
KeyValueIterable labels(
injected_labels_from_plugin_options_, additional_labels,
&parent_->scope_config_->active_plugin_options_view(),
optional_labels_array_, /*is_client=*/true, parent_->otel_plugin_);
if (parent_->otel_plugin_->client_.attempt.duration != nullptr) {
parent_->otel_plugin_->client_.attempt.duration->Record(
absl::ToDoubleSeconds(absl::Now() - start_time_), labels,
opentelemetry::context::Context{});
}
if (parent_->otel_plugin_->client_.attempt
.sent_total_compressed_message_size != nullptr) {
parent_->otel_plugin_->client_.attempt.sent_total_compressed_message_size
->Record(transport_stream_stats != nullptr
? transport_stream_stats->outgoing.data_bytes
: 0,
labels, opentelemetry::context::Context{});
}
if (parent_->otel_plugin_->client_.attempt
.rcvd_total_compressed_message_size != nullptr) {
parent_->otel_plugin_->client_.attempt.rcvd_total_compressed_message_size
->Record(transport_stream_stats != nullptr
? transport_stream_stats->incoming.data_bytes
: 0,
labels, opentelemetry::context::Context{});
}
}
void OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer::RecordCancel(
absl::Status /*cancel_error*/) {}
void OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer::RecordEnd(
const gpr_timespec& /*latency*/) {
if (arena_allocated_) {
this->~CallAttemptTracer();
} else {
delete this;
}
}
void OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer::RecordAnnotation(
absl::string_view /*annotation*/) {
// Not implemented
}
void OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer::RecordAnnotation(
const Annotation& /*annotation*/) {
// Not implemented
}
std::shared_ptr<grpc_core::TcpTracerInterface>
OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer::StartNewTcpTrace() {
// No TCP trace.
return nullptr;
}
void OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer::
AddOptionalLabels(
OptionalLabelComponent component,
std::shared_ptr<std::map<std::string, std::string>> optional_labels) {
optional_labels_array_[static_cast<std::size_t>(component)] =
std::move(optional_labels);
}
//
// OpenTelemetryPlugin::ClientCallTracer
//
OpenTelemetryPlugin::ClientCallTracer::ClientCallTracer(
const grpc_core::Slice& path, grpc_core::Arena* arena,
bool registered_method, OpenTelemetryPlugin* otel_plugin,
std::shared_ptr<OpenTelemetryPlugin::ClientScopeConfig> scope_config)
: path_(path.Ref()),
arena_(arena),
registered_method_(registered_method),
otel_plugin_(otel_plugin),
scope_config_(std::move(scope_config)) {}
OpenTelemetryPlugin::ClientCallTracer::~ClientCallTracer() {}
OpenTelemetryPlugin::ClientCallTracer::CallAttemptTracer*
OpenTelemetryPlugin::ClientCallTracer::StartNewAttempt(
bool is_transparent_retry) {
// We allocate the first attempt on the arena and all subsequent attempts
// on the heap, so that in the common case we don't require a heap
// allocation, nor do we unnecessarily grow the arena.
bool is_first_attempt = true;
{
grpc_core::MutexLock lock(&mu_);
if (transparent_retries_ != 0 || retries_ != 0) {
is_first_attempt = false;
}
if (is_transparent_retry) {
++transparent_retries_;
} else {
++retries_;
}
}
if (is_first_attempt) {
return arena_->New<CallAttemptTracer>(this, /*arena_allocated=*/true);
}
return new CallAttemptTracer(this, /*arena_allocated=*/false);
}
absl::string_view OpenTelemetryPlugin::ClientCallTracer::MethodForStats()
const {
absl::string_view method = absl::StripPrefix(path_.as_string_view(), "/");
if (registered_method_ ||
(otel_plugin_->generic_method_attribute_filter() != nullptr &&
otel_plugin_->generic_method_attribute_filter()(method))) {
return method;
}
return "other";
}
void OpenTelemetryPlugin::ClientCallTracer::RecordAnnotation(
absl::string_view /*annotation*/) {
// Not implemented
}
void OpenTelemetryPlugin::ClientCallTracer::RecordAnnotation(
const Annotation& /*annotation*/) {
// Not implemented
}
} // namespace internal
} // namespace grpc

View File

@ -16,8 +16,8 @@
//
//
#ifndef GRPC_SRC_CPP_EXT_OTEL_OTEL_CALL_TRACER_H
#define GRPC_SRC_CPP_EXT_OTEL_OTEL_CALL_TRACER_H
#ifndef GRPC_SRC_CPP_EXT_OTEL_OTEL_CLIENT_CALL_TRACER_H
#define GRPC_SRC_CPP_EXT_OTEL_OTEL_CLIENT_CALL_TRACER_H
#include <grpc/support/port_platform.h>
@ -42,18 +42,19 @@
#include "src/core/lib/slice/slice_buffer.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/transport.h"
#include "src/cpp/ext/otel/otel_client_filter.h"
#include "src/cpp/ext/otel/otel_plugin.h"
namespace grpc {
namespace internal {
class OpenTelemetryCallTracer : public grpc_core::ClientCallTracer {
class OpenTelemetryPlugin::ClientCallTracer
: public grpc_core::ClientCallTracer {
public:
class OpenTelemetryCallAttemptTracer : public CallAttemptTracer {
class CallAttemptTracer
: public grpc_core::ClientCallTracer::CallAttemptTracer {
public:
OpenTelemetryCallAttemptTracer(const OpenTelemetryCallTracer* parent,
bool arena_allocated);
CallAttemptTracer(const OpenTelemetryPlugin::ClientCallTracer* parent,
bool arena_allocated);
std::string TraceId() override {
// Not implemented
@ -96,7 +97,7 @@ class OpenTelemetryCallTracer : public grpc_core::ClientCallTracer {
optional_labels) override;
private:
const OpenTelemetryCallTracer* parent_;
const ClientCallTracer* parent_;
const bool arena_allocated_;
// Start time (for measuring latency).
absl::Time start_time_;
@ -109,11 +110,11 @@ class OpenTelemetryCallTracer : public grpc_core::ClientCallTracer {
injected_labels_from_plugin_options_;
};
explicit OpenTelemetryCallTracer(OpenTelemetryClientFilter* parent,
grpc_core::Slice path,
grpc_core::Arena* arena,
bool registered_method);
~OpenTelemetryCallTracer() override;
ClientCallTracer(
const grpc_core::Slice& path, grpc_core::Arena* arena,
bool registered_method, OpenTelemetryPlugin* otel_plugin,
std::shared_ptr<OpenTelemetryPlugin::ClientScopeConfig> scope_config);
~ClientCallTracer() override;
std::string TraceId() override {
// Not implemented
@ -130,19 +131,19 @@ class OpenTelemetryCallTracer : public grpc_core::ClientCallTracer {
return false;
}
OpenTelemetryCallAttemptTracer* StartNewAttempt(
bool is_transparent_retry) override;
CallAttemptTracer* StartNewAttempt(bool is_transparent_retry) override;
void RecordAnnotation(absl::string_view /*annotation*/) override;
void RecordAnnotation(const Annotation& /*annotation*/) override;
private:
absl::string_view MethodForStats() const;
const OpenTelemetryClientFilter* parent_;
// Client method.
grpc_core::Slice path_;
grpc_core::Arena* arena_;
const bool registered_method_;
OpenTelemetryPlugin* otel_plugin_;
std::shared_ptr<OpenTelemetryPlugin::ClientScopeConfig> scope_config_;
grpc_core::Mutex mu_;
// Non-transparent attempts per call
uint64_t retries_ ABSL_GUARDED_BY(&mu_) = 0;
@ -153,4 +154,4 @@ class OpenTelemetryCallTracer : public grpc_core::ClientCallTracer {
} // namespace internal
} // namespace grpc
#endif // GRPC_SRC_CPP_EXT_OTEL_OTEL_CALL_TRACER_H
#endif // GRPC_SRC_CPP_EXT_OTEL_OTEL_CLIENT_CALL_TRACER_H

View File

@ -1,328 +0,0 @@
//
//
// 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 <grpc/support/port_platform.h>
#include "src/cpp/ext/otel/otel_client_filter.h"
#include <stdint.h>
#include <array>
#include <functional>
#include <memory>
#include <string>
#include <utility>
#include "absl/functional/any_invocable.h"
#include "absl/status/status.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "absl/types/optional.h"
#include "absl/types/span.h"
#include "opentelemetry/context/context.h"
#include "opentelemetry/metrics/sync_instruments.h"
#include <grpc/status.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include "src/core/client_channel/client_channel_filter.h"
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/channel/context.h"
#include "src/core/lib/channel/status_util.h"
#include "src/core/lib/channel/tcp_tracer.h"
#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/promise/context.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/slice/slice_buffer.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/cpp/ext/otel/key_value_iterable.h"
#include "src/cpp/ext/otel/otel_call_tracer.h"
#include "src/cpp/ext/otel/otel_plugin.h"
namespace grpc {
namespace internal {
//
// OpenTelemetryClientFilter
//
const grpc_channel_filter OpenTelemetryClientFilter::kFilter =
grpc_core::MakePromiseBasedFilter<OpenTelemetryClientFilter,
grpc_core::FilterEndpoint::kClient>(
"otel_client");
absl::StatusOr<OpenTelemetryClientFilter> OpenTelemetryClientFilter::Create(
const grpc_core::ChannelArgs& args, ChannelFilter::Args /*filter_args*/) {
return OpenTelemetryClientFilter(
args.GetOwnedString(GRPC_ARG_SERVER_URI).value_or(""));
}
grpc_core::ArenaPromise<grpc_core::ServerMetadataHandle>
OpenTelemetryClientFilter::MakeCallPromise(
grpc_core::CallArgs call_args,
grpc_core::NextPromiseFactory next_promise_factory) {
auto* path = call_args.client_initial_metadata->get_pointer(
grpc_core::HttpPathMetadata());
bool registered_method = reinterpret_cast<uintptr_t>(
call_args.client_initial_metadata->get(grpc_core::GrpcRegisteredMethod())
.value_or(nullptr));
auto* call_context = grpc_core::GetContext<grpc_call_context_element>();
auto* tracer =
grpc_core::GetContext<grpc_core::Arena>()
->ManagedNew<OpenTelemetryCallTracer>(
this, path != nullptr ? path->Ref() : grpc_core::Slice(),
grpc_core::GetContext<grpc_core::Arena>(), registered_method);
GPR_DEBUG_ASSERT(
call_context[GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE].value ==
nullptr);
call_context[GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE].value = tracer;
call_context[GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE].destroy = nullptr;
return next_promise_factory(std::move(call_args));
}
OpenTelemetryClientFilter::OpenTelemetryClientFilter(std::string target)
: active_plugin_options_view_(
ActivePluginOptionsView::MakeForClient(target)) {
// Use the original target string only if a filter on the attribute is not
// registered or if the filter returns true, otherwise use "other".
if (OpenTelemetryPluginState().target_attribute_filter == nullptr ||
OpenTelemetryPluginState().target_attribute_filter(target)) {
filtered_target_ = std::move(target);
} else {
filtered_target_ = "other";
}
}
//
// OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer
//
OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer::
OpenTelemetryCallAttemptTracer(const OpenTelemetryCallTracer* parent,
bool arena_allocated)
: parent_(parent),
arena_allocated_(arena_allocated),
start_time_(absl::Now()) {
if (OpenTelemetryPluginState().client.attempt.started != nullptr) {
std::array<std::pair<absl::string_view, absl::string_view>, 2>
additional_labels = {
{{OpenTelemetryMethodKey(), parent_->MethodForStats()},
{OpenTelemetryTargetKey(), parent_->parent_->filtered_target()}}};
// We might not have all the injected labels that we want at this point, so
// avoid recording a subset of injected labels here.
OpenTelemetryPluginState().client.attempt.started->Add(
1, KeyValueIterable(/*injected_labels_from_plugin_options=*/{},
additional_labels,
/*active_plugin_options_view=*/nullptr,
/*optional_labels_span=*/{}, /*is_client=*/true));
}
}
void OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer::
RecordReceivedInitialMetadata(grpc_metadata_batch* recv_initial_metadata) {
parent_->parent_->active_plugin_options_view().ForEach(
[&](const InternalOpenTelemetryPluginOption& plugin_option,
size_t /*index*/) {
auto* labels_injector = plugin_option.labels_injector();
if (labels_injector != nullptr) {
injected_labels_from_plugin_options_.push_back(
labels_injector->GetLabels(recv_initial_metadata));
}
return true;
});
}
void OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer::
RecordSendInitialMetadata(grpc_metadata_batch* send_initial_metadata) {
parent_->parent_->active_plugin_options_view().ForEach(
[&](const InternalOpenTelemetryPluginOption& plugin_option,
size_t /*index*/) {
auto* labels_injector = plugin_option.labels_injector();
if (labels_injector != nullptr) {
labels_injector->AddLabels(send_initial_metadata, nullptr);
}
return true;
});
}
void OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer::RecordSendMessage(
const grpc_core::SliceBuffer& send_message) {
RecordAnnotation(
absl::StrFormat("Send message: %ld bytes", send_message.Length()));
}
void OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer::
RecordSendCompressedMessage(
const grpc_core::SliceBuffer& send_compressed_message) {
RecordAnnotation(absl::StrFormat("Send compressed message: %ld bytes",
send_compressed_message.Length()));
}
void OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer::
RecordReceivedMessage(const grpc_core::SliceBuffer& recv_message) {
RecordAnnotation(
absl::StrFormat("Received message: %ld bytes", recv_message.Length()));
}
void OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer::
RecordReceivedDecompressedMessage(
const grpc_core::SliceBuffer& recv_decompressed_message) {
RecordAnnotation(absl::StrFormat("Received decompressed message: %ld bytes",
recv_decompressed_message.Length()));
}
void OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer::
RecordReceivedTrailingMetadata(
absl::Status status, grpc_metadata_batch* /*recv_trailing_metadata*/,
const grpc_transport_stream_stats* transport_stream_stats) {
std::array<std::pair<absl::string_view, absl::string_view>, 3>
additional_labels = {
{{OpenTelemetryMethodKey(), parent_->MethodForStats()},
{OpenTelemetryTargetKey(), parent_->parent_->filtered_target()},
{OpenTelemetryStatusKey(),
grpc_status_code_to_string(
static_cast<grpc_status_code>(status.code()))}}};
KeyValueIterable labels(injected_labels_from_plugin_options_,
additional_labels,
&parent_->parent_->active_plugin_options_view(),
optional_labels_array_, /*is_client=*/true);
if (OpenTelemetryPluginState().client.attempt.duration != nullptr) {
OpenTelemetryPluginState().client.attempt.duration->Record(
absl::ToDoubleSeconds(absl::Now() - start_time_), labels,
opentelemetry::context::Context{});
}
if (OpenTelemetryPluginState()
.client.attempt.sent_total_compressed_message_size != nullptr) {
OpenTelemetryPluginState()
.client.attempt.sent_total_compressed_message_size->Record(
transport_stream_stats != nullptr
? transport_stream_stats->outgoing.data_bytes
: 0,
labels, opentelemetry::context::Context{});
}
if (OpenTelemetryPluginState()
.client.attempt.rcvd_total_compressed_message_size != nullptr) {
OpenTelemetryPluginState()
.client.attempt.rcvd_total_compressed_message_size->Record(
transport_stream_stats != nullptr
? transport_stream_stats->incoming.data_bytes
: 0,
labels, opentelemetry::context::Context{});
}
}
void OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer::RecordCancel(
absl::Status /*cancel_error*/) {}
void OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer::RecordEnd(
const gpr_timespec& /*latency*/) {
if (arena_allocated_) {
this->~OpenTelemetryCallAttemptTracer();
} else {
delete this;
}
}
void OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer::RecordAnnotation(
absl::string_view /*annotation*/) {
// Not implemented
}
void OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer::RecordAnnotation(
const Annotation& /*annotation*/) {
// Not implemented
}
std::shared_ptr<grpc_core::TcpTracerInterface>
OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer::StartNewTcpTrace() {
// No TCP trace.
return nullptr;
}
void OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer::AddOptionalLabels(
OptionalLabelComponent component,
std::shared_ptr<std::map<std::string, std::string>> optional_labels) {
optional_labels_array_[static_cast<std::size_t>(component)] =
std::move(optional_labels);
}
//
// OpenTelemetryCallTracer
//
OpenTelemetryCallTracer::OpenTelemetryCallTracer(
OpenTelemetryClientFilter* parent, grpc_core::Slice path,
grpc_core::Arena* arena, bool registered_method)
: parent_(parent),
path_(std::move(path)),
arena_(arena),
registered_method_(registered_method) {}
OpenTelemetryCallTracer::~OpenTelemetryCallTracer() {}
OpenTelemetryCallTracer::OpenTelemetryCallAttemptTracer*
OpenTelemetryCallTracer::StartNewAttempt(bool is_transparent_retry) {
// We allocate the first attempt on the arena and all subsequent attempts
// on the heap, so that in the common case we don't require a heap
// allocation, nor do we unnecessarily grow the arena.
bool is_first_attempt = true;
{
grpc_core::MutexLock lock(&mu_);
if (transparent_retries_ != 0 || retries_ != 0) {
is_first_attempt = false;
}
if (is_transparent_retry) {
++transparent_retries_;
} else {
++retries_;
}
}
if (is_first_attempt) {
return arena_->New<OpenTelemetryCallAttemptTracer>(
this, /*arena_allocated=*/true);
}
return new OpenTelemetryCallAttemptTracer(this, /*arena_allocated=*/false);
}
absl::string_view OpenTelemetryCallTracer::MethodForStats() const {
absl::string_view method = absl::StripPrefix(path_.as_string_view(), "/");
if (registered_method_ ||
(OpenTelemetryPluginState().generic_method_attribute_filter != nullptr &&
OpenTelemetryPluginState().generic_method_attribute_filter(method))) {
return method;
}
return "other";
}
void OpenTelemetryCallTracer::RecordAnnotation(
absl::string_view /*annotation*/) {
// Not implemented
}
void OpenTelemetryCallTracer::RecordAnnotation(
const Annotation& /*annotation*/) {
// Not implemented
}
} // namespace internal
} // namespace grpc

View File

@ -1,68 +0,0 @@
//
//
// 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.
//
//
#ifndef GRPC_SRC_CPP_EXT_OTEL_OTEL_CLIENT_FILTER_H
#define GRPC_SRC_CPP_EXT_OTEL_OTEL_CLIENT_FILTER_H
#include <grpc/support/port_platform.h>
#include <string>
#include <utility>
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_fwd.h"
#include "src/core/lib/channel/promise_based_filter.h"
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/transport/transport.h"
#include "src/cpp/ext/otel/otel_plugin.h"
namespace grpc {
namespace internal {
class OpenTelemetryClientFilter : public grpc_core::ChannelFilter {
public:
static const grpc_channel_filter kFilter;
static absl::StatusOr<OpenTelemetryClientFilter> Create(
const grpc_core::ChannelArgs& /*args*/,
ChannelFilter::Args /*filter_args*/);
grpc_core::ArenaPromise<grpc_core::ServerMetadataHandle> MakeCallPromise(
grpc_core::CallArgs call_args,
grpc_core::NextPromiseFactory next_promise_factory) override;
absl::string_view filtered_target() const { return filtered_target_; }
const ActivePluginOptionsView& active_plugin_options_view() const {
return active_plugin_options_view_;
}
private:
explicit OpenTelemetryClientFilter(std::string target);
std::string filtered_target_;
ActivePluginOptionsView active_plugin_options_view_;
};
} // namespace internal
} // namespace grpc
#endif // GRPC_SRC_CPP_EXT_OTEL_OTEL_CLIENT_FILTER_H

View File

@ -20,11 +20,13 @@
#include "src/cpp/ext/otel/otel_plugin.h"
#include <memory>
#include <type_traits>
#include <utility>
#include "opentelemetry/metrics/meter.h"
#include "opentelemetry/metrics/meter_provider.h"
#include "opentelemetry/metrics/sync_instruments.h"
#include "opentelemetry/nostd/shared_ptr.h"
#include "opentelemetry/nostd/unique_ptr.h"
@ -37,21 +39,13 @@
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/config/core_configuration.h"
#include "src/core/lib/surface/channel_stack_type.h"
#include "src/cpp/ext/otel/otel_client_filter.h"
#include "src/cpp/ext/otel/key_value_iterable.h"
#include "src/cpp/ext/otel/otel_client_call_tracer.h"
#include "src/cpp/ext/otel/otel_server_call_tracer.h"
namespace grpc {
namespace internal {
// TODO(yashykt): Extend this to allow multiple OpenTelemetry plugins to be
// registered in the same binary.
struct OpenTelemetryPluginState* g_otel_plugin_state_;
const struct OpenTelemetryPluginState& OpenTelemetryPluginState() {
GPR_DEBUG_ASSERT(g_otel_plugin_state_ != nullptr);
return *g_otel_plugin_state_;
}
absl::string_view OpenTelemetryMethodKey() { return "grpc.method"; }
absl::string_view OpenTelemetryStatusKey() { return "grpc.status"; }
@ -60,7 +54,7 @@ absl::string_view OpenTelemetryTargetKey() { return "grpc.target"; }
namespace {
absl::flat_hash_set<std::string> BaseMetrics() {
return absl::flat_hash_set<std::string>{
absl::flat_hash_set<std::string> base_metrics{
std::string(grpc::OpenTelemetryPluginBuilder::
kClientAttemptStartedInstrumentName),
std::string(grpc::OpenTelemetryPluginBuilder::
@ -79,9 +73,67 @@ absl::flat_hash_set<std::string> BaseMetrics() {
kServerCallSentTotalCompressedMessageSizeInstrumentName),
std::string(grpc::OpenTelemetryPluginBuilder::
kServerCallRcvdTotalCompressedMessageSizeInstrumentName)};
grpc_core::GlobalInstrumentsRegistry::ForEach(
[&](const grpc_core::GlobalInstrumentsRegistry::
GlobalInstrumentDescriptor& descriptor) {
if (descriptor.enable_by_default) {
base_metrics.emplace(descriptor.name);
}
});
return base_metrics;
}
} // namespace
class OpenTelemetryPlugin::NPCMetricsKeyValueIterable
: public opentelemetry::common::KeyValueIterable {
public:
NPCMetricsKeyValueIterable(
absl::Span<const absl::string_view> label_keys,
absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_label_keys,
absl::Span<const absl::string_view> optional_label_values,
const OptionalLabelsBitSet& optional_labels_bits)
: label_keys_(label_keys),
label_values_(label_values),
optional_label_keys_(optional_label_keys),
optional_label_values_(optional_label_values),
optional_labels_bits_(optional_labels_bits) {}
bool ForEachKeyValue(opentelemetry::nostd::function_ref<
bool(opentelemetry::nostd::string_view,
opentelemetry::common::AttributeValue)>
callback) const noexcept override {
for (size_t i = 0; i < label_keys_.size(); i++) {
if (!callback(AbslStrViewToOpenTelemetryStrView(label_keys_[i]),
AbslStrViewToOpenTelemetryStrView(label_values_[i]))) {
return false;
}
}
for (size_t i = 0; i < optional_label_keys_.size(); ++i) {
if (!optional_labels_bits_.test(i)) {
continue;
}
if (!callback(
AbslStrViewToOpenTelemetryStrView(optional_label_keys_[i]),
AbslStrViewToOpenTelemetryStrView(optional_label_values_[i]))) {
return false;
}
}
return true;
}
size_t size() const noexcept override {
return label_keys_.size() + optional_labels_bits_.count();
}
private:
absl::Span<const absl::string_view> label_keys_;
absl::Span<const absl::string_view> label_values_;
absl::Span<const absl::string_view> optional_label_keys_;
absl::Span<const absl::string_view> optional_label_values_;
const OptionalLabelsBitSet& optional_labels_bits_;
};
//
// OpenTelemetryPluginBuilderImpl
//
@ -156,112 +208,352 @@ OpenTelemetryPluginBuilderImpl& OpenTelemetryPluginBuilderImpl::AddPluginOption(
return *this;
}
OpenTelemetryPluginBuilderImpl&
OpenTelemetryPluginBuilderImpl::AddOptionalLabel(
absl::string_view optional_label_key) {
if (optional_label_keys_ == nullptr) {
optional_label_keys_ = std::make_shared<std::set<absl::string_view>>();
}
optional_label_keys_->emplace(optional_label_key);
return *this;
}
absl::Status OpenTelemetryPluginBuilderImpl::BuildAndRegisterGlobal() {
opentelemetry::nostd::shared_ptr<opentelemetry::metrics::MeterProvider>
meter_provider = meter_provider_;
delete g_otel_plugin_state_;
g_otel_plugin_state_ = new struct OpenTelemetryPluginState;
if (meter_provider == nullptr) {
if (meter_provider_ == nullptr) {
return absl::OkStatus();
}
auto meter = meter_provider->GetMeter("grpc-c++", GRPC_CPP_VERSION_STRING);
if (metrics_.contains(grpc::OpenTelemetryPluginBuilder::
kClientAttemptStartedInstrumentName)) {
g_otel_plugin_state_->client.attempt.started = meter->CreateUInt64Counter(
grpc_core::GlobalStatsPluginRegistry::RegisterStatsPlugin(
std::make_shared<OpenTelemetryPlugin>(
metrics_, meter_provider_, std::move(target_selector_),
std::move(target_attribute_filter_),
std::move(generic_method_attribute_filter_),
std::move(server_selector_), std::move(plugin_options_),
std::move(optional_label_keys_)));
return absl::OkStatus();
}
OpenTelemetryPlugin::OpenTelemetryPlugin(
const absl::flat_hash_set<std::string>& metrics,
opentelemetry::nostd::shared_ptr<opentelemetry::metrics::MeterProvider>
meter_provider,
absl::AnyInvocable<bool(absl::string_view /*target*/) const>
target_selector,
absl::AnyInvocable<bool(absl::string_view /*target*/) const>
target_attribute_filter,
absl::AnyInvocable<bool(absl::string_view /*generic_method*/) const>
generic_method_attribute_filter,
absl::AnyInvocable<bool(const grpc_core::ChannelArgs& /*args*/) const>
server_selector,
std::vector<std::unique_ptr<InternalOpenTelemetryPluginOption>>
plugin_options,
std::shared_ptr<std::set<absl::string_view>> optional_label_keys)
: meter_provider_(std::move(meter_provider)),
target_selector_(std::move(target_selector)),
server_selector_(std::move(server_selector)),
target_attribute_filter_(std::move(target_attribute_filter)),
generic_method_attribute_filter_(
std::move(generic_method_attribute_filter)),
plugin_options_(std::move(plugin_options)) {
auto meter = meter_provider_->GetMeter("grpc-c++", GRPC_CPP_VERSION_STRING);
// Per-call metrics.
if (metrics.contains(grpc::OpenTelemetryPluginBuilder::
kClientAttemptStartedInstrumentName)) {
client_.attempt.started = meter->CreateUInt64Counter(
std::string(grpc::OpenTelemetryPluginBuilder::
kClientAttemptStartedInstrumentName),
"Number of client call attempts started", "{attempt}");
}
if (metrics_.contains(grpc::OpenTelemetryPluginBuilder::
kClientAttemptDurationInstrumentName)) {
g_otel_plugin_state_->client.attempt.duration =
meter->CreateDoubleHistogram(
std::string(grpc::OpenTelemetryPluginBuilder::
kClientAttemptDurationInstrumentName),
"End-to-end time taken to complete a client call attempt", "s");
if (metrics.contains(grpc::OpenTelemetryPluginBuilder::
kClientAttemptDurationInstrumentName)) {
client_.attempt.duration = meter->CreateDoubleHistogram(
std::string(grpc::OpenTelemetryPluginBuilder::
kClientAttemptDurationInstrumentName),
"End-to-end time taken to complete a client call attempt", "s");
}
if (metrics_.contains(
if (metrics.contains(
grpc::OpenTelemetryPluginBuilder::
kClientAttemptSentTotalCompressedMessageSizeInstrumentName)) {
g_otel_plugin_state_->client.attempt.sent_total_compressed_message_size =
client_.attempt.sent_total_compressed_message_size =
meter->CreateUInt64Histogram(
std::string(
grpc::OpenTelemetryPluginBuilder::
kClientAttemptSentTotalCompressedMessageSizeInstrumentName),
"Compressed message bytes sent per client call attempt", "By");
}
if (metrics_.contains(
if (metrics.contains(
grpc::OpenTelemetryPluginBuilder::
kClientAttemptRcvdTotalCompressedMessageSizeInstrumentName)) {
g_otel_plugin_state_->client.attempt.rcvd_total_compressed_message_size =
client_.attempt.rcvd_total_compressed_message_size =
meter->CreateUInt64Histogram(
std::string(
grpc::OpenTelemetryPluginBuilder::
kClientAttemptRcvdTotalCompressedMessageSizeInstrumentName),
"Compressed message bytes received per call attempt", "By");
}
if (metrics_.contains(
if (metrics.contains(
grpc::OpenTelemetryPluginBuilder::kServerCallStartedInstrumentName)) {
g_otel_plugin_state_->server.call.started = meter->CreateUInt64Counter(
server_.call.started = meter->CreateUInt64Counter(
std::string(
grpc::OpenTelemetryPluginBuilder::kServerCallStartedInstrumentName),
"Number of server calls started", "{call}");
}
if (metrics_.contains(grpc::OpenTelemetryPluginBuilder::
kServerCallDurationInstrumentName)) {
g_otel_plugin_state_->server.call.duration = meter->CreateDoubleHistogram(
if (metrics.contains(grpc::OpenTelemetryPluginBuilder::
kServerCallDurationInstrumentName)) {
server_.call.duration = meter->CreateDoubleHistogram(
std::string(grpc::OpenTelemetryPluginBuilder::
kServerCallDurationInstrumentName),
"End-to-end time taken to complete a call from server transport's "
"perspective",
"s");
}
if (metrics_.contains(
if (metrics.contains(
grpc::OpenTelemetryPluginBuilder::
kServerCallSentTotalCompressedMessageSizeInstrumentName)) {
g_otel_plugin_state_->server.call.sent_total_compressed_message_size =
server_.call.sent_total_compressed_message_size =
meter->CreateUInt64Histogram(
std::string(
grpc::OpenTelemetryPluginBuilder::
kServerCallSentTotalCompressedMessageSizeInstrumentName),
"Compressed message bytes sent per server call", "By");
}
if (metrics_.contains(
if (metrics.contains(
grpc::OpenTelemetryPluginBuilder::
kServerCallRcvdTotalCompressedMessageSizeInstrumentName)) {
g_otel_plugin_state_->server.call.rcvd_total_compressed_message_size =
server_.call.rcvd_total_compressed_message_size =
meter->CreateUInt64Histogram(
std::string(
grpc::OpenTelemetryPluginBuilder::
kServerCallRcvdTotalCompressedMessageSizeInstrumentName),
"Compressed message bytes received per server call", "By");
}
g_otel_plugin_state_->target_attribute_filter =
std::move(target_attribute_filter_);
g_otel_plugin_state_->server_selector = std::move(server_selector_);
g_otel_plugin_state_->generic_method_attribute_filter =
std::move(generic_method_attribute_filter_);
g_otel_plugin_state_->meter_provider = std::move(meter_provider);
g_otel_plugin_state_->plugin_options = std::move(plugin_options_);
grpc_core::ServerCallTracerFactory::RegisterGlobal(
new grpc::internal::OpenTelemetryServerCallTracerFactory());
grpc_core::CoreConfiguration::RegisterBuilder(
[target_selector = std::move(target_selector_)](
grpc_core::CoreConfiguration::Builder* builder) mutable {
builder->channel_init()
->RegisterFilter(
GRPC_CLIENT_CHANNEL,
&grpc::internal::OpenTelemetryClientFilter::kFilter)
.If([target_selector = std::move(target_selector)](
const grpc_core::ChannelArgs& args) {
// Only register the filter if no channel selector has been set or
// the target selector returns true for the target.
return target_selector == nullptr ||
target_selector(
args.GetString(GRPC_ARG_SERVER_URI).value_or(""));
});
// Non-per-call metrics.
grpc_core::GlobalInstrumentsRegistry::ForEach(
[&, this](const grpc_core::GlobalInstrumentsRegistry::
GlobalInstrumentDescriptor& descriptor) {
GPR_ASSERT(descriptor.optional_label_keys.size() <=
kOptionalLabelsSizeLimit);
if (instruments_data_.size() < descriptor.index + 1) {
instruments_data_.resize(descriptor.index + 1);
}
if (!metrics.contains(descriptor.name)) {
return;
}
switch (descriptor.instrument_type) {
case grpc_core::GlobalInstrumentsRegistry::InstrumentType::kCounter:
switch (descriptor.value_type) {
case grpc_core::GlobalInstrumentsRegistry::ValueType::kUInt64:
instruments_data_[descriptor.index].instrument =
meter->CreateUInt64Counter(
std::string(descriptor.name),
std::string(descriptor.description),
std::string(descriptor.unit));
break;
case grpc_core::GlobalInstrumentsRegistry::ValueType::kDouble:
instruments_data_[descriptor.index].instrument =
meter->CreateDoubleCounter(
std::string(descriptor.name),
std::string(descriptor.description),
std::string(descriptor.unit));
break;
default:
grpc_core::Crash(
absl::StrFormat("Unknown or unsupported value type: %d",
descriptor.value_type));
}
break;
case grpc_core::GlobalInstrumentsRegistry::InstrumentType::kHistogram:
switch (descriptor.value_type) {
case grpc_core::GlobalInstrumentsRegistry::ValueType::kUInt64:
instruments_data_[descriptor.index].instrument =
meter->CreateUInt64Histogram(
std::string(descriptor.name),
std::string(descriptor.description),
std::string(descriptor.unit));
break;
case grpc_core::GlobalInstrumentsRegistry::ValueType::kDouble:
instruments_data_[descriptor.index].instrument =
meter->CreateDoubleHistogram(
std::string(descriptor.name),
std::string(descriptor.description),
std::string(descriptor.unit));
break;
default:
grpc_core::Crash(
absl::StrFormat("Unknown or unsupported value type: %d",
descriptor.value_type));
}
break;
// TODO(yashkt, yijiem): implement gauges.
case grpc_core::GlobalInstrumentsRegistry::InstrumentType::kGauge:
switch (descriptor.value_type) {
case grpc_core::GlobalInstrumentsRegistry::ValueType::kInt64:
break;
case grpc_core::GlobalInstrumentsRegistry::ValueType::kDouble:
break;
default:
grpc_core::Crash(
absl::StrFormat("Unknown or unsupported value type: %d",
descriptor.value_type));
}
break;
case grpc_core::GlobalInstrumentsRegistry::InstrumentType::
kCallbackGauge:
switch (descriptor.value_type) {
case grpc_core::GlobalInstrumentsRegistry::ValueType::kInt64:
break;
case grpc_core::GlobalInstrumentsRegistry::ValueType::kDouble:
break;
default:
grpc_core::Crash(
absl::StrFormat("Unknown or unsupported value type: %d",
descriptor.value_type));
}
break;
default:
grpc_core::Crash(absl::StrFormat("Unknown instrument_type: %d",
descriptor.instrument_type));
}
for (size_t i = 0; i < descriptor.optional_label_keys.size(); ++i) {
if (optional_label_keys->find(descriptor.optional_label_keys[i]) !=
optional_label_keys->end()) {
instruments_data_[descriptor.index].optional_labels_bits.set(i);
}
}
});
return absl::OkStatus();
}
std::pair<bool, std::shared_ptr<grpc_core::StatsPlugin::ScopeConfig>>
OpenTelemetryPlugin::IsEnabledForChannel(const ChannelScope& scope) const {
if (target_selector_ == nullptr || target_selector_(scope.target())) {
return {true, std::make_shared<ClientScopeConfig>(this, scope)};
}
return {false, nullptr};
}
std::pair<bool, std::shared_ptr<grpc_core::StatsPlugin::ScopeConfig>>
OpenTelemetryPlugin::IsEnabledForServer(
const grpc_core::ChannelArgs& args) const {
// Return true only if there is no server selector registered or if the server
// selector returns true.
if (server_selector_ == nullptr || server_selector_(args)) {
return {true, std::make_shared<ServerScopeConfig>(this, args)};
}
return {false, nullptr};
}
void OpenTelemetryPlugin::AddCounter(
grpc_core::GlobalInstrumentsRegistry::GlobalUInt64CounterHandle handle,
uint64_t value, absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) {
const auto& instrument_data = instruments_data_.at(handle.index);
if (absl::holds_alternative<Disabled>(instrument_data.instrument)) {
// This instrument is disabled.
return;
}
GPR_ASSERT(absl::holds_alternative<
std::unique_ptr<opentelemetry::metrics::Counter<uint64_t>>>(
instrument_data.instrument));
const auto& descriptor =
grpc_core::GlobalInstrumentsRegistry::GetInstrumentDescriptor(handle);
GPR_ASSERT(descriptor.label_keys.size() == label_values.size());
GPR_ASSERT(descriptor.optional_label_keys.size() == optional_values.size());
absl::get<std::unique_ptr<opentelemetry::metrics::Counter<uint64_t>>>(
instrument_data.instrument)
->Add(value, NPCMetricsKeyValueIterable(
descriptor.label_keys, label_values,
descriptor.optional_label_keys, optional_values,
instrument_data.optional_labels_bits));
}
void OpenTelemetryPlugin::AddCounter(
grpc_core::GlobalInstrumentsRegistry::GlobalDoubleCounterHandle handle,
double value, absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) {
const auto& instrument_data = instruments_data_.at(handle.index);
if (absl::holds_alternative<Disabled>(instrument_data.instrument)) {
// This instrument is disabled.
return;
}
GPR_ASSERT(absl::holds_alternative<
std::unique_ptr<opentelemetry::metrics::Counter<double>>>(
instrument_data.instrument));
const auto& descriptor =
grpc_core::GlobalInstrumentsRegistry::GetInstrumentDescriptor(handle);
GPR_ASSERT(descriptor.label_keys.size() == label_values.size());
GPR_ASSERT(descriptor.optional_label_keys.size() == optional_values.size());
absl::get<std::unique_ptr<opentelemetry::metrics::Counter<double>>>(
instrument_data.instrument)
->Add(value, NPCMetricsKeyValueIterable(
descriptor.label_keys, label_values,
descriptor.optional_label_keys, optional_values,
instrument_data.optional_labels_bits));
}
void OpenTelemetryPlugin::RecordHistogram(
grpc_core::GlobalInstrumentsRegistry::GlobalUInt64HistogramHandle handle,
uint64_t value, absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) {
const auto& instrument_data = instruments_data_.at(handle.index);
if (absl::holds_alternative<Disabled>(instrument_data.instrument)) {
// This instrument is disabled.
return;
}
GPR_ASSERT(absl::holds_alternative<
std::unique_ptr<opentelemetry::metrics::Histogram<uint64_t>>>(
instrument_data.instrument));
const auto& descriptor =
grpc_core::GlobalInstrumentsRegistry::GetInstrumentDescriptor(handle);
GPR_ASSERT(descriptor.label_keys.size() == label_values.size());
GPR_ASSERT(descriptor.optional_label_keys.size() == optional_values.size());
absl::get<std::unique_ptr<opentelemetry::metrics::Histogram<uint64_t>>>(
instrument_data.instrument)
->Record(value,
NPCMetricsKeyValueIterable(descriptor.label_keys, label_values,
descriptor.optional_label_keys,
optional_values,
instrument_data.optional_labels_bits),
opentelemetry::context::Context{});
}
void OpenTelemetryPlugin::RecordHistogram(
grpc_core::GlobalInstrumentsRegistry::GlobalDoubleHistogramHandle handle,
double value, absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) {
const auto& instrument_data = instruments_data_.at(handle.index);
if (absl::holds_alternative<Disabled>(instrument_data.instrument)) {
// This instrument is disabled.
return;
}
GPR_ASSERT(absl::holds_alternative<
std::unique_ptr<opentelemetry::metrics::Histogram<double>>>(
instrument_data.instrument));
const auto& descriptor =
grpc_core::GlobalInstrumentsRegistry::GetInstrumentDescriptor(handle);
GPR_ASSERT(descriptor.label_keys.size() == label_values.size());
GPR_ASSERT(descriptor.optional_label_keys.size() == optional_values.size());
absl::get<std::unique_ptr<opentelemetry::metrics::Histogram<double>>>(
instrument_data.instrument)
->Record(value,
NPCMetricsKeyValueIterable(descriptor.label_keys, label_values,
descriptor.optional_label_keys,
optional_values,
instrument_data.optional_labels_bits),
opentelemetry::context::Context{});
}
grpc_core::ClientCallTracer* OpenTelemetryPlugin::GetClientCallTracer(
const grpc_core::Slice& path, bool registered_method,
std::shared_ptr<grpc_core::StatsPlugin::ScopeConfig> scope_config) {
return grpc_core::GetContext<grpc_core::Arena>()
->ManagedNew<ClientCallTracer>(
path, grpc_core::GetContext<grpc_core::Arena>(), registered_method,
this,
std::static_pointer_cast<OpenTelemetryPlugin::ClientScopeConfig>(
scope_config));
}
grpc_core::ServerCallTracer* OpenTelemetryPlugin::GetServerCallTracer(
std::shared_ptr<grpc_core::StatsPlugin::ScopeConfig> scope_config) {
return grpc_core::GetContext<grpc_core::Arena>()
->ManagedNew<ServerCallTracer>(
this,
std::static_pointer_cast<OpenTelemetryPlugin::ServerScopeConfig>(
scope_config));
}
} // namespace internal
@ -324,6 +616,12 @@ OpenTelemetryPluginBuilder& OpenTelemetryPluginBuilder::AddPluginOption(
return *this;
}
OpenTelemetryPluginBuilder& OpenTelemetryPluginBuilder::AddOptionalLabel(
absl::string_view optional_label_key) {
impl_->AddOptionalLabel(optional_label_key);
return *this;
}
absl::Status OpenTelemetryPluginBuilder::BuildAndRegisterGlobal() {
return impl_->BuildAndRegisterGlobal();
}

View File

@ -40,6 +40,7 @@
#include <grpcpp/ext/otel_plugin.h>
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/metrics.h"
#include "src/core/lib/transport/metadata_batch.h"
namespace grpc {
@ -112,41 +113,6 @@ class InternalOpenTelemetryPluginOption
virtual const grpc::internal::LabelsInjector* labels_injector() const = 0;
};
struct OpenTelemetryPluginState {
struct Client {
struct Attempt {
std::unique_ptr<opentelemetry::metrics::Counter<uint64_t>> started;
std::unique_ptr<opentelemetry::metrics::Histogram<double>> duration;
std::unique_ptr<opentelemetry::metrics::Histogram<uint64_t>>
sent_total_compressed_message_size;
std::unique_ptr<opentelemetry::metrics::Histogram<uint64_t>>
rcvd_total_compressed_message_size;
} attempt;
} client;
struct Server {
struct Call {
std::unique_ptr<opentelemetry::metrics::Counter<uint64_t>> started;
std::unique_ptr<opentelemetry::metrics::Histogram<double>> duration;
std::unique_ptr<opentelemetry::metrics::Histogram<uint64_t>>
sent_total_compressed_message_size;
std::unique_ptr<opentelemetry::metrics::Histogram<uint64_t>>
rcvd_total_compressed_message_size;
} call;
} server;
opentelemetry::nostd::shared_ptr<opentelemetry::metrics::MeterProvider>
meter_provider;
absl::AnyInvocable<bool(absl::string_view /*target*/) const>
target_attribute_filter;
absl::AnyInvocable<bool(absl::string_view /*generic_method*/) const>
generic_method_attribute_filter;
absl::AnyInvocable<bool(const grpc_core::ChannelArgs& /*args*/) const>
server_selector;
std::vector<std::unique_ptr<InternalOpenTelemetryPluginOption>>
plugin_options;
};
const struct OpenTelemetryPluginState& OpenTelemetryPluginState();
// Tags
absl::string_view OpenTelemetryMethodKey();
absl::string_view OpenTelemetryStatusKey();
@ -202,6 +168,9 @@ class OpenTelemetryPluginBuilderImpl {
generic_method_attribute_filter);
OpenTelemetryPluginBuilderImpl& AddPluginOption(
std::unique_ptr<InternalOpenTelemetryPluginOption> option);
// Records \a optional_label_key on all metrics that provide it.
OpenTelemetryPluginBuilderImpl& AddOptionalLabel(
absl::string_view optional_label_key);
absl::Status BuildAndRegisterGlobal();
private:
@ -217,53 +186,232 @@ class OpenTelemetryPluginBuilderImpl {
server_selector_;
std::vector<std::unique_ptr<InternalOpenTelemetryPluginOption>>
plugin_options_;
std::shared_ptr<std::set<absl::string_view>> optional_label_keys_;
};
// Creates a convenience wrapper to help iterate over only those plugin options
// that are active over a given channel/server.
class ActivePluginOptionsView {
class OpenTelemetryPlugin : public grpc_core::StatsPlugin {
public:
static ActivePluginOptionsView MakeForClient(absl::string_view target) {
return ActivePluginOptionsView(
[target](const InternalOpenTelemetryPluginOption& plugin_option) {
return plugin_option.IsActiveOnClientChannel(target);
});
}
static ActivePluginOptionsView MakeForServer(
const grpc_core::ChannelArgs& args) {
return ActivePluginOptionsView(
[&args](const InternalOpenTelemetryPluginOption& plugin_option) {
return plugin_option.IsActiveOnServer(args);
});
}
bool ForEach(
absl::FunctionRef<bool(const InternalOpenTelemetryPluginOption&, size_t)>
func) const {
for (size_t i = 0; i < OpenTelemetryPluginState().plugin_options.size();
++i) {
const auto& plugin_option = OpenTelemetryPluginState().plugin_options[i];
if (active_mask_[i] && !func(*plugin_option, i)) {
return false;
}
}
return true;
}
OpenTelemetryPlugin(
const absl::flat_hash_set<std::string>& metrics,
opentelemetry::nostd::shared_ptr<opentelemetry::metrics::MeterProvider>
meter_provider,
absl::AnyInvocable<bool(absl::string_view /*target*/) const>
target_selector,
absl::AnyInvocable<bool(absl::string_view /*target*/) const>
target_attribute_filter,
absl::AnyInvocable<bool(absl::string_view /*generic_method*/) const>
generic_method_attribute_filter,
absl::AnyInvocable<bool(const grpc_core::ChannelArgs& /*args*/) const>
server_selector,
std::vector<std::unique_ptr<InternalOpenTelemetryPluginOption>>
plugin_options,
std::shared_ptr<std::set<absl::string_view>> optional_label_keys);
private:
explicit ActivePluginOptionsView(
absl::FunctionRef<bool(const InternalOpenTelemetryPluginOption&)> func) {
for (size_t i = 0; i < OpenTelemetryPluginState().plugin_options.size();
++i) {
const auto& plugin_option = OpenTelemetryPluginState().plugin_options[i];
if (plugin_option != nullptr && func(*plugin_option)) {
active_mask_.set(i);
class ClientCallTracer;
class KeyValueIterable;
class NPCMetricsKeyValueIterable;
class ServerCallTracer;
// Creates a convenience wrapper to help iterate over only those plugin
// options that are active over a given channel/server.
class ActivePluginOptionsView {
public:
static ActivePluginOptionsView MakeForClient(
absl::string_view target, const OpenTelemetryPlugin* otel_plugin) {
return ActivePluginOptionsView(
[target](const InternalOpenTelemetryPluginOption& plugin_option) {
return plugin_option.IsActiveOnClientChannel(target);
},
otel_plugin);
}
static ActivePluginOptionsView MakeForServer(
const grpc_core::ChannelArgs& args,
const OpenTelemetryPlugin* otel_plugin) {
return ActivePluginOptionsView(
[&args](const InternalOpenTelemetryPluginOption& plugin_option) {
return plugin_option.IsActiveOnServer(args);
},
otel_plugin);
}
bool ForEach(absl::FunctionRef<
bool(const InternalOpenTelemetryPluginOption&, size_t)>
func,
const OpenTelemetryPlugin* otel_plugin) const {
for (size_t i = 0; i < otel_plugin->plugin_options().size(); ++i) {
const auto& plugin_option = otel_plugin->plugin_options()[i];
if (active_mask_[i] && !func(*plugin_option, i)) {
return false;
}
}
return true;
}
private:
explicit ActivePluginOptionsView(
absl::FunctionRef<bool(const InternalOpenTelemetryPluginOption&)> func,
const OpenTelemetryPlugin* otel_plugin) {
for (size_t i = 0; i < otel_plugin->plugin_options().size(); ++i) {
const auto& plugin_option = otel_plugin->plugin_options()[i];
if (plugin_option != nullptr && func(*plugin_option)) {
active_mask_.set(i);
}
}
}
std::bitset<64> active_mask_;
};
class ClientScopeConfig : public grpc_core::StatsPlugin::ScopeConfig {
public:
ClientScopeConfig(const OpenTelemetryPlugin* otel_plugin,
const ChannelScope& scope)
: active_plugin_options_view_(ActivePluginOptionsView::MakeForClient(
scope.target(), otel_plugin)),
filtered_target_(
// Use the original target string only if a filter on the
// attribute is not registered or if the filter returns true,
// otherwise use "other".
otel_plugin->target_attribute_filter() == nullptr ||
otel_plugin->target_attribute_filter()(scope.target())
? scope.target()
: "other") {}
const ActivePluginOptionsView& active_plugin_options_view() const {
return active_plugin_options_view_;
}
absl::string_view filtered_target() const { return filtered_target_; }
private:
ActivePluginOptionsView active_plugin_options_view_;
std::string filtered_target_;
};
class ServerScopeConfig : public grpc_core::StatsPlugin::ScopeConfig {
public:
ServerScopeConfig(const OpenTelemetryPlugin* otel_plugin,
const grpc_core::ChannelArgs& args)
: active_plugin_options_view_(
ActivePluginOptionsView::MakeForServer(args, otel_plugin)) {}
const ActivePluginOptionsView& active_plugin_options_view() const {
return active_plugin_options_view_;
}
private:
ActivePluginOptionsView active_plugin_options_view_;
};
struct ClientMetrics {
struct Attempt {
std::unique_ptr<opentelemetry::metrics::Counter<uint64_t>> started;
std::unique_ptr<opentelemetry::metrics::Histogram<double>> duration;
std::unique_ptr<opentelemetry::metrics::Histogram<uint64_t>>
sent_total_compressed_message_size;
std::unique_ptr<opentelemetry::metrics::Histogram<uint64_t>>
rcvd_total_compressed_message_size;
} attempt;
};
struct ServerMetrics {
struct Call {
std::unique_ptr<opentelemetry::metrics::Counter<uint64_t>> started;
std::unique_ptr<opentelemetry::metrics::Histogram<double>> duration;
std::unique_ptr<opentelemetry::metrics::Histogram<uint64_t>>
sent_total_compressed_message_size;
std::unique_ptr<opentelemetry::metrics::Histogram<uint64_t>>
rcvd_total_compressed_message_size;
} call;
};
// StatsPlugin:
std::pair<bool, std::shared_ptr<grpc_core::StatsPlugin::ScopeConfig>>
IsEnabledForChannel(const ChannelScope& scope) const override;
std::pair<bool, std::shared_ptr<grpc_core::StatsPlugin::ScopeConfig>>
IsEnabledForServer(const grpc_core::ChannelArgs& args) const override;
void AddCounter(
grpc_core::GlobalInstrumentsRegistry::GlobalUInt64CounterHandle handle,
uint64_t value, absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) override;
void AddCounter(
grpc_core::GlobalInstrumentsRegistry::GlobalDoubleCounterHandle handle,
double value, absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) override;
void RecordHistogram(
grpc_core::GlobalInstrumentsRegistry::GlobalUInt64HistogramHandle handle,
uint64_t value, absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) override;
void RecordHistogram(
grpc_core::GlobalInstrumentsRegistry::GlobalDoubleHistogramHandle handle,
double value, absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) override;
void SetGauge(
grpc_core::GlobalInstrumentsRegistry::GlobalInt64GaugeHandle /*handle*/,
int64_t /*value*/, absl::Span<const absl::string_view> /*label_values*/,
absl::Span<const absl::string_view> /*optional_values*/) override {}
void SetGauge(
grpc_core::GlobalInstrumentsRegistry::GlobalDoubleGaugeHandle /*handle*/,
double /*value*/, absl::Span<const absl::string_view> /*label_values*/,
absl::Span<const absl::string_view> /*optional_values*/) override {}
// TODO(yashkt, yijiem): implement async instrument.
void AddCallback(grpc_core::RegisteredMetricCallback* /*callback*/) override {
}
void RemoveCallback(
grpc_core::RegisteredMetricCallback* /*callback*/) override {}
grpc_core::ClientCallTracer* GetClientCallTracer(
const grpc_core::Slice& path, bool registered_method,
std::shared_ptr<grpc_core::StatsPlugin::ScopeConfig> scope_config)
override;
grpc_core::ServerCallTracer* GetServerCallTracer(
std::shared_ptr<grpc_core::StatsPlugin::ScopeConfig> scope_config)
override;
const absl::AnyInvocable<bool(const grpc_core::ChannelArgs& /*args*/) const>&
server_selector() const {
return server_selector_;
}
const absl::AnyInvocable<bool(absl::string_view /*target*/) const>&
target_attribute_filter() const {
return target_attribute_filter_;
}
const absl::AnyInvocable<bool(absl::string_view /*generic_method*/) const>&
generic_method_attribute_filter() const {
return generic_method_attribute_filter_;
}
const std::vector<std::unique_ptr<InternalOpenTelemetryPluginOption>>&
plugin_options() const {
return plugin_options_;
}
std::bitset<64> active_mask_;
// Instruments for per-call metrics.
ClientMetrics client_;
ServerMetrics server_;
// Instruments for non-per-call metrics.
struct Disabled {};
using Instrument = absl::variant<
Disabled, std::unique_ptr<opentelemetry::metrics::Counter<uint64_t>>,
std::unique_ptr<opentelemetry::metrics::Counter<double>>,
std::unique_ptr<opentelemetry::metrics::Histogram<uint64_t>>,
std::unique_ptr<opentelemetry::metrics::Histogram<double>>>;
static constexpr int kOptionalLabelsSizeLimit = 64;
using OptionalLabelsBitSet = std::bitset<kOptionalLabelsSizeLimit>;
struct InstrumentData {
Instrument instrument;
OptionalLabelsBitSet optional_labels_bits;
};
std::vector<InstrumentData> instruments_data_;
opentelemetry::nostd::shared_ptr<opentelemetry::metrics::MeterProvider>
meter_provider_;
absl::AnyInvocable<bool(absl::string_view /*target*/) const> target_selector_;
absl::AnyInvocable<bool(const grpc_core::ChannelArgs& /*args*/) const>
server_selector_;
absl::AnyInvocable<bool(absl::string_view /*target*/) const>
target_attribute_filter_;
absl::AnyInvocable<bool(absl::string_view /*generic_method*/) const>
generic_method_attribute_filter_;
std::vector<std::unique_ptr<InternalOpenTelemetryPluginOption>>
plugin_options_;
};
} // namespace internal

View File

@ -28,7 +28,6 @@
#include "absl/functional/any_invocable.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "absl/types/optional.h"
@ -50,127 +49,11 @@
namespace grpc {
namespace internal {
namespace {
// OpenTelemetryServerCallTracer implementation
class OpenTelemetryServerCallTracer : public grpc_core::ServerCallTracer {
public:
explicit OpenTelemetryServerCallTracer(const grpc_core::ChannelArgs& args)
: start_time_(absl::Now()),
active_plugin_options_view_(
ActivePluginOptionsView::MakeForServer(args)),
injected_labels_from_plugin_options_(
OpenTelemetryPluginState().plugin_options.size()) {}
std::string TraceId() override {
// Not implemented
return "";
}
std::string SpanId() override {
// Not implemented
return "";
}
bool IsSampled() override {
// Not implemented
return false;
}
// Please refer to `grpc_transport_stream_op_batch_payload` for details on
// arguments.
void RecordSendInitialMetadata(
grpc_metadata_batch* send_initial_metadata) override {
active_plugin_options_view_.ForEach(
[&](const InternalOpenTelemetryPluginOption& plugin_option,
size_t index) {
auto* labels_injector = plugin_option.labels_injector();
if (labels_injector != nullptr) {
labels_injector->AddLabels(
send_initial_metadata,
injected_labels_from_plugin_options_[index].get());
}
return true;
});
}
void RecordSendTrailingMetadata(
grpc_metadata_batch* /*send_trailing_metadata*/) override;
void RecordSendMessage(const grpc_core::SliceBuffer& send_message) override {
RecordAnnotation(
absl::StrFormat("Send message: %ld bytes", send_message.Length()));
}
void RecordSendCompressedMessage(
const grpc_core::SliceBuffer& send_compressed_message) override {
RecordAnnotation(absl::StrFormat("Send compressed message: %ld bytes",
send_compressed_message.Length()));
}
void RecordReceivedInitialMetadata(
grpc_metadata_batch* recv_initial_metadata) override;
void RecordReceivedMessage(
const grpc_core::SliceBuffer& recv_message) override {
RecordAnnotation(
absl::StrFormat("Received message: %ld bytes", recv_message.Length()));
}
void RecordReceivedDecompressedMessage(
const grpc_core::SliceBuffer& recv_decompressed_message) override {
RecordAnnotation(absl::StrFormat("Received decompressed message: %ld bytes",
recv_decompressed_message.Length()));
}
void RecordReceivedTrailingMetadata(
grpc_metadata_batch* /*recv_trailing_metadata*/) override {}
void RecordCancel(grpc_error_handle /*cancel_error*/) override {
elapsed_time_ = absl::Now() - start_time_;
}
void RecordEnd(const grpc_call_final_info* final_info) override;
void RecordAnnotation(absl::string_view /*annotation*/) override {
// Not implemented
}
void RecordAnnotation(const Annotation& /*annotation*/) override {
// Not implemented
}
std::shared_ptr<grpc_core::TcpTracerInterface> StartNewTcpTrace() override {
// No TCP trace.
return nullptr;
}
private:
absl::string_view MethodForStats() const {
absl::string_view method = absl::StripPrefix(path_.as_string_view(), "/");
if (registered_method_ ||
(OpenTelemetryPluginState().generic_method_attribute_filter !=
nullptr &&
OpenTelemetryPluginState().generic_method_attribute_filter(method))) {
return method;
}
return "other";
}
absl::Time start_time_;
absl::Duration elapsed_time_;
grpc_core::Slice path_;
bool registered_method_;
ActivePluginOptionsView active_plugin_options_view_;
// TODO(yashykt): It's wasteful to do this per call. When we re-haul the stats
// infrastructure, this should move to be done per server.
std::vector<std::unique_ptr<LabelsIterable>>
injected_labels_from_plugin_options_;
};
void OpenTelemetryServerCallTracer::RecordReceivedInitialMetadata(
void OpenTelemetryPlugin::ServerCallTracer::RecordReceivedInitialMetadata(
grpc_metadata_batch* recv_initial_metadata) {
path_ =
recv_initial_metadata->get_pointer(grpc_core::HttpPathMetadata())->Ref();
active_plugin_options_view_.ForEach(
scope_config_->active_plugin_options_view().ForEach(
[&](const InternalOpenTelemetryPluginOption& plugin_option,
size_t index) {
auto* labels_injector = plugin_option.labels_injector();
@ -179,31 +62,48 @@ void OpenTelemetryServerCallTracer::RecordReceivedInitialMetadata(
labels_injector->GetLabels(recv_initial_metadata);
}
return true;
});
},
otel_plugin_);
registered_method_ =
recv_initial_metadata->get(grpc_core::GrpcRegisteredMethod())
.value_or(nullptr) != nullptr;
std::array<std::pair<absl::string_view, absl::string_view>, 1>
additional_labels = {{{OpenTelemetryMethodKey(), MethodForStats()}}};
if (OpenTelemetryPluginState().server.call.started != nullptr) {
if (otel_plugin_->server_.call.started != nullptr) {
// We might not have all the injected labels that we want at this point, so
// avoid recording a subset of injected labels here.
OpenTelemetryPluginState().server.call.started->Add(
otel_plugin_->server_.call.started->Add(
1, KeyValueIterable(/*injected_labels_from_plugin_options=*/{},
additional_labels,
/*active_plugin_options_view=*/nullptr, {},
/*is_client=*/false));
/*is_client=*/false, otel_plugin_));
}
}
void OpenTelemetryServerCallTracer::RecordSendTrailingMetadata(
void OpenTelemetryPlugin::ServerCallTracer::RecordSendInitialMetadata(
grpc_metadata_batch* send_initial_metadata) {
scope_config_->active_plugin_options_view().ForEach(
[&](const InternalOpenTelemetryPluginOption& plugin_option,
size_t index) {
auto* labels_injector = plugin_option.labels_injector();
if (labels_injector != nullptr) {
labels_injector->AddLabels(
send_initial_metadata,
injected_labels_from_plugin_options_[index].get());
}
return true;
},
otel_plugin_);
}
void OpenTelemetryPlugin::ServerCallTracer::RecordSendTrailingMetadata(
grpc_metadata_batch* /*send_trailing_metadata*/) {
// We need to record the time when the trailing metadata was sent to
// mark the completeness of the request.
elapsed_time_ = absl::Now() - start_time_;
}
void OpenTelemetryServerCallTracer::RecordEnd(
void OpenTelemetryPlugin::ServerCallTracer::RecordEnd(
const grpc_call_final_info* final_info) {
std::array<std::pair<absl::string_view, absl::string_view>, 2>
additional_labels = {
@ -214,47 +114,25 @@ void OpenTelemetryServerCallTracer::RecordEnd(
KeyValueIterable labels(
injected_labels_from_plugin_options_, additional_labels,
/*active_plugin_options_view=*/nullptr, /*optional_labels_span=*/{},
/*is_client=*/false);
if (OpenTelemetryPluginState().server.call.duration != nullptr) {
OpenTelemetryPluginState().server.call.duration->Record(
/*is_client=*/false, otel_plugin_);
if (otel_plugin_->server_.call.duration != nullptr) {
otel_plugin_->server_.call.duration->Record(
absl::ToDoubleSeconds(elapsed_time_), labels,
opentelemetry::context::Context{});
}
if (OpenTelemetryPluginState()
.server.call.sent_total_compressed_message_size != nullptr) {
OpenTelemetryPluginState()
.server.call.sent_total_compressed_message_size->Record(
final_info->stats.transport_stream_stats.outgoing.data_bytes,
labels, opentelemetry::context::Context{});
if (otel_plugin_->server_.call.sent_total_compressed_message_size !=
nullptr) {
otel_plugin_->server_.call.sent_total_compressed_message_size->Record(
final_info->stats.transport_stream_stats.outgoing.data_bytes, labels,
opentelemetry::context::Context{});
}
if (OpenTelemetryPluginState()
.server.call.rcvd_total_compressed_message_size != nullptr) {
OpenTelemetryPluginState()
.server.call.rcvd_total_compressed_message_size->Record(
final_info->stats.transport_stream_stats.incoming.data_bytes,
labels, opentelemetry::context::Context{});
if (otel_plugin_->server_.call.rcvd_total_compressed_message_size !=
nullptr) {
otel_plugin_->server_.call.rcvd_total_compressed_message_size->Record(
final_info->stats.transport_stream_stats.incoming.data_bytes, labels,
opentelemetry::context::Context{});
}
}
} // namespace
//
// OpenTelemetryServerCallTracerFactory
//
grpc_core::ServerCallTracer*
OpenTelemetryServerCallTracerFactory::CreateNewServerCallTracer(
grpc_core::Arena* arena, const grpc_core::ChannelArgs& args) {
return arena->ManagedNew<OpenTelemetryServerCallTracer>(args);
}
bool OpenTelemetryServerCallTracerFactory::IsServerTraced(
const grpc_core::ChannelArgs& args) {
// Return true only if there is no server selector registered or if the server
// selector returns true.
return OpenTelemetryPluginState().server_selector == nullptr ||
OpenTelemetryPluginState().server_selector(args);
}
} // namespace internal
} // namespace grpc

View File

@ -21,21 +21,116 @@
#include <grpc/support/port_platform.h>
#include "absl/strings/strip.h"
#include "src/core/lib/channel/call_tracer.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/cpp/ext/otel/otel_plugin.h"
namespace grpc {
namespace internal {
class OpenTelemetryServerCallTracerFactory
: public grpc_core::ServerCallTracerFactory {
public:
grpc_core::ServerCallTracer* CreateNewServerCallTracer(
grpc_core::Arena* arena,
const grpc_core::ChannelArgs& channel_args) override;
// OpenTelemetryPlugin::ServerCallTracer implementation
bool IsServerTraced(const grpc_core::ChannelArgs& args) override;
class OpenTelemetryPlugin::ServerCallTracer
: public grpc_core::ServerCallTracer {
public:
ServerCallTracer(
OpenTelemetryPlugin* otel_plugin,
std::shared_ptr<OpenTelemetryPlugin::ServerScopeConfig> scope_config)
: start_time_(absl::Now()),
injected_labels_from_plugin_options_(
otel_plugin->plugin_options().size()),
otel_plugin_(otel_plugin),
scope_config_(std::move(scope_config)) {}
std::string TraceId() override {
// Not implemented
return "";
}
std::string SpanId() override {
// Not implemented
return "";
}
bool IsSampled() override {
// Not implemented
return false;
}
// Please refer to `grpc_transport_stream_op_batch_payload` for details on
// arguments.
void RecordSendInitialMetadata(
grpc_metadata_batch* send_initial_metadata) override;
void RecordSendTrailingMetadata(
grpc_metadata_batch* /*send_trailing_metadata*/) override;
void RecordSendMessage(const grpc_core::SliceBuffer& send_message) override {
RecordAnnotation(
absl::StrFormat("Send message: %ld bytes", send_message.Length()));
}
void RecordSendCompressedMessage(
const grpc_core::SliceBuffer& send_compressed_message) override {
RecordAnnotation(absl::StrFormat("Send compressed message: %ld bytes",
send_compressed_message.Length()));
}
void RecordReceivedInitialMetadata(
grpc_metadata_batch* recv_initial_metadata) override;
void RecordReceivedMessage(
const grpc_core::SliceBuffer& recv_message) override {
RecordAnnotation(
absl::StrFormat("Received message: %ld bytes", recv_message.Length()));
}
void RecordReceivedDecompressedMessage(
const grpc_core::SliceBuffer& recv_decompressed_message) override {
RecordAnnotation(absl::StrFormat("Received decompressed message: %ld bytes",
recv_decompressed_message.Length()));
}
void RecordReceivedTrailingMetadata(
grpc_metadata_batch* /*recv_trailing_metadata*/) override {}
void RecordCancel(grpc_error_handle /*cancel_error*/) override {
elapsed_time_ = absl::Now() - start_time_;
}
void RecordEnd(const grpc_call_final_info* final_info) override;
void RecordAnnotation(absl::string_view /*annotation*/) override {
// Not implemented
}
void RecordAnnotation(const Annotation& /*annotation*/) override {
// Not implemented
}
std::shared_ptr<grpc_core::TcpTracerInterface> StartNewTcpTrace() override {
// No TCP trace.
return nullptr;
}
private:
absl::string_view MethodForStats() const {
absl::string_view method = absl::StripPrefix(path_.as_string_view(), "/");
if (registered_method_ ||
(otel_plugin_->generic_method_attribute_filter() != nullptr &&
otel_plugin_->generic_method_attribute_filter()(method))) {
return method;
}
return "other";
}
absl::Time start_time_;
absl::Duration elapsed_time_;
grpc_core::Slice path_;
bool registered_method_;
std::vector<std::unique_ptr<LabelsIterable>>
injected_labels_from_plugin_options_;
OpenTelemetryPlugin* otel_plugin_;
std::shared_ptr<OpenTelemetryPlugin::ServerScopeConfig> scope_config_;
};
} // namespace internal

View File

@ -1168,7 +1168,7 @@ TEST_F(PickFirstTest, MetricValues) {
const absl::string_view kLabelValues[] = {target_};
auto stats_plugin = std::make_shared<FakeStatsPlugin>(
nullptr, /*use_disabled_by_default_metrics=*/true);
stats_plugin_group_.push_back(stats_plugin);
stats_plugin_group_.AddStatsPlugin(stats_plugin, nullptr);
// Send an update containing two addresses.
constexpr std::array<absl::string_view, 2> kAddresses = {
"ipv4:127.0.0.1:443", "ipv4:127.0.0.1:444"};

View File

@ -1084,7 +1084,7 @@ TEST_F(WeightedRoundRobinTest, MetricValues) {
const absl::string_view kOptionalLabelValues[] = {kLocalityName};
auto stats_plugin = std::make_shared<FakeStatsPlugin>(
nullptr, /*use_disabled_by_default_metrics=*/true);
stats_plugin_group_.push_back(stats_plugin);
stats_plugin_group_.AddStatsPlugin(stats_plugin, nullptr);
// Send address list to LB policy.
const std::array<absl::string_view, 3> kAddresses = {
"ipv4:127.0.0.1:441", "ipv4:127.0.0.1:442", "ipv4:127.0.0.1:443"};

View File

@ -90,6 +90,7 @@ def grpc_core_end2end_test(name, shard_count = 10, tags = []):
"//src/core:stats_data",
"//src/core:status_helper",
"//src/core:time",
"//test/core/util:fake_stats_plugin",
"//test/core/util:grpc_test_util",
"//test/core/util:test_lb_policies",
],
@ -170,6 +171,7 @@ def grpc_core_end2end_test(name, shard_count = 10, tags = []):
"//src/core:time",
"//test/core/event_engine/fuzzing_event_engine",
"//test/core/event_engine/fuzzing_event_engine:fuzzing_event_engine_proto",
"//test/core/util:fake_stats_plugin",
"//test/core/util:fuzz_config_vars",
"//test/core/util:fuzz_config_vars_proto",
"//test/core/util:grpc_test_util",

View File

@ -33,6 +33,7 @@
#include "src/core/lib/channel/channel_fwd.h"
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/channel/context.h"
#include "src/core/lib/channel/metrics.h"
#include "src/core/lib/channel/promise_based_filter.h"
#include "src/core/lib/channel/tcp_tracer.h"
#include "src/core/lib/config/core_configuration.h"
@ -50,6 +51,7 @@
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/transport.h"
#include "test/core/end2end/end2end_tests.h"
#include "test/core/util/fake_stats_plugin.h"
namespace grpc_core {
namespace {
@ -130,33 +132,6 @@ class FakeCallTracer : public ClientCallTracer {
grpc_transport_stream_stats
FakeCallTracer::FakeCallAttemptTracer::transport_stream_stats_;
class FakeClientFilter : public ChannelFilter {
public:
static const grpc_channel_filter kFilter;
static absl::StatusOr<FakeClientFilter> Create(
const ChannelArgs& /*args*/, ChannelFilter::Args /*filter_args*/) {
return FakeClientFilter();
}
ArenaPromise<ServerMetadataHandle> MakeCallPromise(
CallArgs call_args, NextPromiseFactory next_promise_factory) override {
auto* call_context = GetContext<grpc_call_context_element>();
auto* tracer = GetContext<Arena>()->ManagedNew<FakeCallTracer>();
GPR_DEBUG_ASSERT(
call_context[GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE].value ==
nullptr);
call_context[GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE].value = tracer;
call_context[GRPC_CONTEXT_CALL_TRACER_ANNOTATION_INTERFACE].destroy =
nullptr;
return next_promise_factory(std::move(call_args));
}
};
const grpc_channel_filter FakeClientFilter::kFilter =
MakePromiseBasedFilter<FakeClientFilter, FilterEndpoint::kClient>(
"fake_client");
class FakeServerCallTracer : public ServerCallTracer {
public:
~FakeServerCallTracer() override {}
@ -203,11 +178,18 @@ class FakeServerCallTracer : public ServerCallTracer {
grpc_transport_stream_stats FakeServerCallTracer::transport_stream_stats_;
class FakeServerCallTracerFactory : public ServerCallTracerFactory {
// TODO(yijiem): figure out how to reuse FakeStatsPlugin instead of
// inheriting and overriding it here.
class NewFakeStatsPlugin : public FakeStatsPlugin {
public:
ServerCallTracer* CreateNewServerCallTracer(
Arena* arena, const ChannelArgs& /*args*/) override {
return arena->ManagedNew<FakeServerCallTracer>();
ClientCallTracer* GetClientCallTracer(
const Slice& /*path*/, bool /*registered_method*/,
std::shared_ptr<StatsPlugin::ScopeConfig> /*scope_config*/) override {
return GetContext<Arena>()->ManagedNew<FakeCallTracer>();
}
ServerCallTracer* GetServerCallTracer(
std::shared_ptr<StatsPlugin::ScopeConfig> /*scope_config*/) override {
return GetContext<Arena>()->ManagedNew<FakeServerCallTracer>();
}
};
@ -219,12 +201,8 @@ CORE_END2END_TEST(Http2FullstackSingleHopTest, StreamStats) {
g_mu = new Mutex();
g_client_call_ended_notify = new Notification();
g_server_call_ended_notify = new Notification();
CoreConfiguration::RegisterBuilder([](CoreConfiguration::Builder* builder) {
builder->channel_init()->RegisterFilter<FakeClientFilter>(
GRPC_CLIENT_CHANNEL);
});
ServerCallTracerFactory::RegisterGlobal(new FakeServerCallTracerFactory);
GlobalStatsPluginRegistry::RegisterStatsPlugin(
std::make_shared<NewFakeStatsPlugin>());
auto send_from_client = RandomSlice(10);
auto send_from_server = RandomSlice(20);
CoreEnd2endTest::IncomingStatusOnClient server_status;

View File

@ -37,6 +37,7 @@
#include <grpc/status.h>
#include "src/core/ext/transport/chaotic_good/client_transport.h"
#include "src/core/lib/config/core_configuration.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/timer_manager.h"
#include "src/core/lib/promise/activity.h"

View File

@ -36,6 +36,7 @@
#include <grpc/grpc.h>
#include <grpc/status.h>
#include "src/core/lib/config/core_configuration.h"
#include "src/core/lib/promise/if.h"
#include "src/core/lib/promise/loop.h"
#include "src/core/lib/promise/seq.h"

View File

@ -122,17 +122,17 @@ namespace {
template <typename HandleType>
absl::optional<HandleType> FindInstrument(
const absl::flat_hash_map<
absl::string_view,
GlobalInstrumentsRegistry::GlobalInstrumentDescriptor>& instruments,
const std::vector<GlobalInstrumentsRegistry::GlobalInstrumentDescriptor>&
instruments,
absl::string_view name, GlobalInstrumentsRegistry::ValueType value_type,
GlobalInstrumentsRegistry::InstrumentType instrument_type) {
auto it = instruments.find(name);
if (it != instruments.end() && it->second.value_type == value_type &&
it->second.instrument_type == instrument_type) {
HandleType handle;
handle.index = it->second.index;
return handle;
for (const auto& descriptor : instruments) {
if (descriptor.name == name && descriptor.value_type == value_type &&
descriptor.instrument_type == instrument_type) {
HandleType handle;
handle.index = descriptor.index;
return handle;
}
}
return absl::nullopt;
}
@ -216,9 +216,11 @@ GlobalInstrumentsRegistryTestPeer::FindCallbackDoubleGaugeHandleByName(
GlobalInstrumentsRegistry::GlobalInstrumentDescriptor*
GlobalInstrumentsRegistryTestPeer::FindMetricDescriptorByName(
absl::string_view name) {
auto& instruments = GlobalInstrumentsRegistry::GetInstrumentList();
auto it = instruments.find(name);
if (it != instruments.end()) return &it->second;
for (auto& descriptor : GlobalInstrumentsRegistry::GetInstrumentList()) {
if (descriptor.name == name) {
return &descriptor;
}
}
return nullptr;
}

View File

@ -204,6 +204,8 @@ std::string MakeLabelString(
class FakeStatsPlugin : public StatsPlugin {
public:
class ScopeConfig : public StatsPlugin::ScopeConfig {};
explicit FakeStatsPlugin(
absl::AnyInvocable<bool(const ChannelScope& /*scope*/) const>
channel_filter = nullptr,
@ -266,13 +268,16 @@ class FakeStatsPlugin : public StatsPlugin {
});
}
bool IsEnabledForChannel(const ChannelScope& scope) const override {
if (channel_filter_ == nullptr) return true;
return channel_filter_(scope);
std::pair<bool, std::shared_ptr<StatsPlugin::ScopeConfig>>
IsEnabledForChannel(const ChannelScope& scope) const override {
if (channel_filter_ == nullptr || channel_filter_(scope)) {
return {true, nullptr};
}
return {false, nullptr};
}
bool IsEnabledForServer(const ChannelArgs& /*args*/) const override {
return false;
std::pair<bool, std::shared_ptr<StatsPlugin::ScopeConfig>> IsEnabledForServer(
const ChannelArgs& /*args*/) const override {
return {true, nullptr};
}
void AddCounter(
@ -382,6 +387,16 @@ class FakeStatsPlugin : public StatsPlugin {
callbacks_.erase(callback);
}
ClientCallTracer* GetClientCallTracer(
const Slice& /*path*/, bool /*registered_method*/,
std::shared_ptr<StatsPlugin::ScopeConfig> /*scope_config*/) override {
return nullptr;
}
ServerCallTracer* GetServerCallTracer(
std::shared_ptr<StatsPlugin::ScopeConfig> /*scope_config*/) override {
return nullptr;
}
absl::optional<uint64_t> GetCounterValue(
GlobalInstrumentsRegistry::GlobalUInt64CounterHandle handle,
absl::Span<const absl::string_view> label_values,

View File

@ -41,6 +41,7 @@ grpc_cc_library(
deps = [
"//:grpc++",
"//src/cpp/ext/otel:otel_plugin",
"//test/core/util:fake_stats_plugin",
"//test/core/util:grpc_test_util",
"//test/cpp/end2end:test_service_impl",
],

View File

@ -18,10 +18,15 @@
#include "src/cpp/ext/otel/otel_plugin.h"
#include <type_traits>
#include "absl/functional/any_invocable.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "opentelemetry/metrics/provider.h"
#include "opentelemetry/nostd/variant.h"
#include "opentelemetry/sdk/common/attribute_utils.h"
#include "opentelemetry/sdk/metrics/data/point_data.h"
#include "opentelemetry/sdk/metrics/meter_provider.h"
#include "opentelemetry/sdk/metrics/metric_reader.h"
@ -38,6 +43,73 @@ namespace grpc {
namespace testing {
namespace {
#define GRPC_ARG_SERVER_SELECTOR_KEY "grpc.testing.server_selector_key"
#define GRPC_ARG_SERVER_SELECTOR_VALUE "grpc.testing.server_selector_value"
template <typename T>
void PopulateLabelMap(
T label_keys, T label_values,
std::unordered_map<std::string,
opentelemetry::sdk::common::OwnedAttributeValue>*
label_maps) {
for (size_t i = 0; i < label_keys.size(); ++i) {
(*label_maps)[std::string(label_keys[i])] = std::string(label_values[i]);
}
}
MATCHER_P4(AttributesEq, label_keys, label_values, optional_label_keys,
optional_label_values, "") {
std::unordered_map<std::string,
opentelemetry::sdk::common::OwnedAttributeValue>
label_map;
PopulateLabelMap(label_keys, label_values, &label_map);
PopulateLabelMap(optional_label_keys, optional_label_values, &label_map);
return ::testing::ExplainMatchResult(
::testing::UnorderedElementsAreArray(label_map),
arg.attributes.GetAttributes(), result_listener);
}
template <typename T>
auto IntOrDoubleEq(T result) {
return ::testing::Eq(result);
}
template <>
auto IntOrDoubleEq(double result) {
return ::testing::DoubleEq(result);
}
MATCHER_P(CounterResultEq, result, "") {
return ::testing::ExplainMatchResult(
::testing::VariantWith<opentelemetry::sdk::metrics::SumPointData>(
::testing::Field(
&opentelemetry::sdk::metrics::SumPointData::value_,
::testing::VariantWith<std::remove_cv_t<decltype(result)>>(
IntOrDoubleEq(result)))),
arg.point_data, result_listener);
}
MATCHER_P4(HistogramResultEq, sum, min, max, count, "") {
return ::testing::ExplainMatchResult(
::testing::VariantWith<opentelemetry::sdk::metrics::HistogramPointData>(
::testing::AllOf(
::testing::Field(
&opentelemetry::sdk::metrics::HistogramPointData::sum_,
::testing::VariantWith<std::remove_cv_t<decltype(sum)>>(
IntOrDoubleEq(sum))),
::testing::Field(
&opentelemetry::sdk::metrics::HistogramPointData::min_,
::testing::VariantWith<std::remove_cv_t<decltype(min)>>(
IntOrDoubleEq(min))),
::testing::Field(
&opentelemetry::sdk::metrics::HistogramPointData::max_,
::testing::VariantWith<std::remove_cv_t<decltype(max)>>(
IntOrDoubleEq(max))),
::testing::Field(
&opentelemetry::sdk::metrics::HistogramPointData::count_,
::testing::Eq(count)))),
arg.point_data, result_listener);
}
TEST(OpenTelemetryPluginBuildTest, ApiDependency) {
opentelemetry::metrics::Provider::GetMeterProvider();
}
@ -933,6 +1005,354 @@ TEST_F(OpenTelemetryPluginOptionEnd2EndTest,
EXPECT_EQ(absl::get<std::string>(server_attributes.at("key5")), "value5");
}
using OpenTelemetryPluginNPCMetricsTest = OpenTelemetryPluginEnd2EndTest;
TEST_F(OpenTelemetryPluginNPCMetricsTest, RecordUInt64Counter) {
constexpr absl::string_view kMetricName = "uint64_counter";
constexpr int kCounterValues[] = {1, 2, 3};
constexpr int64_t kCounterResult = 6;
constexpr std::array<absl::string_view, 2> kLabelKeys = {"label_key_1",
"label_key_2"};
constexpr std::array<absl::string_view, 2> kOptionalLabelKeys = {
"optional_label_key_1", "optional_label_key_2"};
constexpr std::array<absl::string_view, 2> kLabelValues = {"label_value_1",
"label_value_2"};
constexpr std::array<absl::string_view, 2> kOptionalLabelValues = {
"optional_label_value_1", "optional_label_value_2"};
auto handle = grpc_core::GlobalInstrumentsRegistry::RegisterUInt64Counter(
kMetricName, "A simple uint64 counter.", "unit", kLabelKeys,
kOptionalLabelKeys, /*enable_by_default=*/true);
Init(std::move(Options()
.set_metric_names({kMetricName})
.set_target_selector([](absl::string_view target) {
return absl::StartsWith(target, "dns:///");
})
.add_optional_label(kOptionalLabelKeys[0])
.add_optional_label(kOptionalLabelKeys[1])));
auto stats_plugins =
grpc_core::GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
grpc_core::StatsPlugin::ChannelScope("dns:///localhost:8080", ""));
for (auto v : kCounterValues) {
stats_plugins.AddCounter(handle, v, kLabelValues, kOptionalLabelValues);
}
auto data = ReadCurrentMetricsData(
[&](const absl::flat_hash_map<
std::string,
std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>&
data) { return !data.contains(kMetricName); });
EXPECT_THAT(data, ::testing::ElementsAre(::testing::Pair(
kMetricName, ::testing::ElementsAre(::testing::AllOf(
AttributesEq(kLabelKeys, kLabelValues,
kOptionalLabelKeys,
kOptionalLabelValues),
CounterResultEq(kCounterResult))))));
}
TEST_F(OpenTelemetryPluginNPCMetricsTest, RecordDoubleCounter) {
constexpr absl::string_view kMetricName = "double_counter";
constexpr double kCounterValues[] = {1.23, 2.34, 3.45};
constexpr double kCounterResult = 7.02;
constexpr std::array<absl::string_view, 2> kLabelKeys = {"label_key_1",
"label_key_2"};
constexpr std::array<absl::string_view, 2> kOptionalLabelKeys = {
"optional_label_key_1", "optional_label_key_2"};
constexpr std::array<absl::string_view, 2> kLabelValues = {"label_value_1",
"label_value_2"};
constexpr std::array<absl::string_view, 2> kOptionalLabelValues = {
"optional_label_value_1", "optional_label_value_2"};
auto handle = grpc_core::GlobalInstrumentsRegistry::RegisterDoubleCounter(
kMetricName, "A simple double counter.", "unit", kLabelKeys,
kOptionalLabelKeys, /*enable_by_default=*/false);
Init(std::move(Options()
.set_metric_names({kMetricName})
.set_target_selector([](absl::string_view target) {
return absl::StartsWith(target, "dns:///");
})
.add_optional_label(kOptionalLabelKeys[0])
.add_optional_label(kOptionalLabelKeys[1])));
auto stats_plugins =
grpc_core::GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
grpc_core::StatsPlugin::ChannelScope("dns:///localhost:8080", ""));
for (auto v : kCounterValues) {
stats_plugins.AddCounter(handle, v, kLabelValues, kOptionalLabelValues);
}
auto data = ReadCurrentMetricsData(
[&](const absl::flat_hash_map<
std::string,
std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>&
data) { return !data.contains(kMetricName); });
EXPECT_THAT(data, ::testing::ElementsAre(::testing::Pair(
kMetricName, ::testing::ElementsAre(::testing::AllOf(
AttributesEq(kLabelKeys, kLabelValues,
kOptionalLabelKeys,
kOptionalLabelValues),
CounterResultEq(kCounterResult))))));
}
TEST_F(OpenTelemetryPluginNPCMetricsTest, RecordUInt64Histogram) {
constexpr absl::string_view kMetricName = "uint64_histogram";
constexpr int kHistogramValues[] = {1, 1, 2, 3, 4, 4, 5, 6};
constexpr int64_t kSum = 26;
constexpr int64_t kMin = 1;
constexpr int64_t kMax = 6;
constexpr int64_t kCount = 8;
constexpr std::array<absl::string_view, 2> kLabelKeys = {"label_key_1",
"label_key_2"};
constexpr std::array<absl::string_view, 2> kOptionalLabelKeys = {
"optional_label_key_1", "optional_label_key_2"};
constexpr std::array<absl::string_view, 2> kLabelValues = {"label_value_1",
"label_value_2"};
constexpr std::array<absl::string_view, 2> kOptionalLabelValues = {
"optional_label_value_1", "optional_label_value_2"};
auto handle = grpc_core::GlobalInstrumentsRegistry::RegisterUInt64Histogram(
kMetricName, "A simple uint64 histogram.", "unit", kLabelKeys,
kOptionalLabelKeys, /*enable_by_default=*/true);
Init(std::move(
Options()
.set_metric_names({kMetricName})
.set_server_selector([](const grpc_core::ChannelArgs& args) {
return args.GetString(GRPC_ARG_SERVER_SELECTOR_KEY) ==
GRPC_ARG_SERVER_SELECTOR_VALUE;
})
.add_optional_label(kOptionalLabelKeys[0])
.add_optional_label(kOptionalLabelKeys[1])));
grpc_core::ChannelArgs args;
args = args.Set(GRPC_ARG_SERVER_SELECTOR_KEY, GRPC_ARG_SERVER_SELECTOR_VALUE);
auto stats_plugins =
grpc_core::GlobalStatsPluginRegistry::GetStatsPluginsForServer(args);
for (auto v : kHistogramValues) {
stats_plugins.RecordHistogram(handle, v, kLabelValues,
kOptionalLabelValues);
}
auto data = ReadCurrentMetricsData(
[&](const absl::flat_hash_map<
std::string,
std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>&
data) { return !data.contains(kMetricName); });
EXPECT_THAT(data,
::testing::ElementsAre(::testing::Pair(
kMetricName,
::testing::ElementsAre(::testing::AllOf(
AttributesEq(kLabelKeys, kLabelValues, kOptionalLabelKeys,
kOptionalLabelValues),
HistogramResultEq(kSum, kMin, kMax, kCount))))));
}
TEST_F(OpenTelemetryPluginNPCMetricsTest, RecordDoubleHistogram) {
constexpr absl::string_view kMetricName = "double_histogram";
constexpr double kHistogramValues[] = {1.1, 1.2, 2.2, 3.3,
4.4, 4.5, 5.5, 6.6};
constexpr double kSum = 28.8;
constexpr double kMin = 1.1;
constexpr double kMax = 6.6;
constexpr double kCount = 8;
constexpr std::array<absl::string_view, 2> kLabelKeys = {"label_key_1",
"label_key_2"};
constexpr std::array<absl::string_view, 2> kOptionalLabelKeys = {
"optional_label_key_1", "optional_label_key_2"};
constexpr std::array<absl::string_view, 2> kLabelValues = {"label_value_1",
"label_value_2"};
constexpr std::array<absl::string_view, 2> kOptionalLabelValues = {
"optional_label_value_1", "optional_label_value_2"};
auto handle = grpc_core::GlobalInstrumentsRegistry::RegisterDoubleHistogram(
kMetricName, "A simple double histogram.", "unit", kLabelKeys,
kOptionalLabelKeys, /*enable_by_default=*/true);
Init(std::move(
Options()
.set_metric_names({kMetricName})
.set_server_selector([](const grpc_core::ChannelArgs& args) {
return args.GetString(GRPC_ARG_SERVER_SELECTOR_KEY) ==
GRPC_ARG_SERVER_SELECTOR_VALUE;
})
.add_optional_label(kOptionalLabelKeys[0])
.add_optional_label(kOptionalLabelKeys[1])));
grpc_core::ChannelArgs args;
args = args.Set(GRPC_ARG_SERVER_SELECTOR_KEY, GRPC_ARG_SERVER_SELECTOR_VALUE);
auto stats_plugins =
grpc_core::GlobalStatsPluginRegistry::GetStatsPluginsForServer(args);
for (auto v : kHistogramValues) {
stats_plugins.RecordHistogram(handle, v, kLabelValues,
kOptionalLabelValues);
}
auto data = ReadCurrentMetricsData(
[&](const absl::flat_hash_map<
std::string,
std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>&
data) { return !data.contains(kMetricName); });
EXPECT_THAT(data,
::testing::ElementsAre(::testing::Pair(
kMetricName,
::testing::ElementsAre(::testing::AllOf(
AttributesEq(kLabelKeys, kLabelValues, kOptionalLabelKeys,
kOptionalLabelValues),
HistogramResultEq(kSum, kMin, kMax, kCount))))));
}
TEST_F(OpenTelemetryPluginNPCMetricsTest,
RegisterMultipleOpenTelemetryPlugins) {
constexpr absl::string_view kMetricName = "yet_another_double_histogram";
constexpr std::array<absl::string_view, 2> kLabelKeys = {"label_key_1",
"label_key_2"};
constexpr std::array<absl::string_view, 2> kOptionalLabelKeys = {
"optional_label_key_1", "optional_label_key_2"};
constexpr std::array<absl::string_view, 2> kLabelValues = {"label_value_1",
"label_value_2"};
constexpr std::array<absl::string_view, 2> kOptionalLabelValues = {
"optional_label_value_1", "optional_label_value_2"};
auto handle = grpc_core::GlobalInstrumentsRegistry::RegisterDoubleHistogram(
kMetricName, "A simple double histogram.", "unit", kLabelKeys,
kOptionalLabelKeys, /*enable_by_default=*/true);
// Build and register a separate OpenTelemetryPlugin and verify its histogram
// recording.
grpc::internal::OpenTelemetryPluginBuilderImpl ot_builder;
auto reader = BuildAndRegisterOpenTelemetryPlugin(std::move(
Options()
.set_metric_names({kMetricName})
.set_server_selector([](const grpc_core::ChannelArgs& args) {
return args.GetString(GRPC_ARG_SERVER_SELECTOR_KEY) ==
GRPC_ARG_SERVER_SELECTOR_VALUE;
})
.add_optional_label(kOptionalLabelKeys[0])
.add_optional_label(kOptionalLabelKeys[1])));
EXPECT_EQ(ot_builder.BuildAndRegisterGlobal(), absl::OkStatus());
grpc_core::ChannelArgs args;
args = args.Set(GRPC_ARG_SERVER_SELECTOR_KEY, GRPC_ARG_SERVER_SELECTOR_VALUE);
{
constexpr double kHistogramValues[] = {1.23, 2.34, 3.45, 4.56};
constexpr double kSum = 11.58;
constexpr double kMin = 1.23;
constexpr double kMax = 4.56;
constexpr int kCount = 4;
auto stats_plugins =
grpc_core::GlobalStatsPluginRegistry::GetStatsPluginsForServer(args);
for (auto v : kHistogramValues) {
stats_plugins.RecordHistogram(handle, v, kLabelValues,
kOptionalLabelValues);
}
auto data = ReadCurrentMetricsData(
[&](const absl::flat_hash_map<
std::string,
std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>&
data) { return !data.contains(kMetricName); },
reader.get());
EXPECT_THAT(
data, ::testing::ElementsAre(::testing::Pair(
kMetricName,
::testing::ElementsAre(::testing::AllOf(
AttributesEq(kLabelKeys, kLabelValues, kOptionalLabelKeys,
kOptionalLabelValues),
HistogramResultEq(kSum, kMin, kMax, kCount))))));
}
// Now build and register another OpenTelemetryPlugin using the test fixture
// and record histogram.
constexpr double kHistogramValues[] = {1.1, 1.2, 2.2, 3.3,
4.4, 4.5, 5.5, 6.6};
constexpr double kSum = 28.8;
constexpr double kMin = 1.1;
constexpr double kMax = 6.6;
constexpr int kCount = 8;
Init(std::move(
Options()
.set_metric_names({kMetricName})
.set_server_selector([](const grpc_core::ChannelArgs& args) {
return args.GetString(GRPC_ARG_SERVER_SELECTOR_KEY) ==
GRPC_ARG_SERVER_SELECTOR_VALUE;
})
.add_optional_label(kOptionalLabelKeys[0])
.add_optional_label(kOptionalLabelKeys[1])));
auto stats_plugins =
grpc_core::GlobalStatsPluginRegistry::GetStatsPluginsForServer(args);
for (auto v : kHistogramValues) {
stats_plugins.RecordHistogram(handle, v, kLabelValues,
kOptionalLabelValues);
}
auto data = ReadCurrentMetricsData(
[&](const absl::flat_hash_map<
std::string,
std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>&
data) { return !data.contains(kMetricName); });
EXPECT_THAT(data,
::testing::ElementsAre(::testing::Pair(
kMetricName,
::testing::ElementsAre(::testing::AllOf(
AttributesEq(kLabelKeys, kLabelValues, kOptionalLabelKeys,
kOptionalLabelValues),
HistogramResultEq(kSum, kMin, kMax, kCount))))));
// Verify that the first plugin gets the data as well.
data = ReadCurrentMetricsData(
[&](const absl::flat_hash_map<
std::string,
std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>&
data) { return !data.contains(kMetricName); },
reader.get());
EXPECT_THAT(data,
::testing::ElementsAre(::testing::Pair(
kMetricName,
::testing::ElementsAre(::testing::AllOf(
AttributesEq(kLabelKeys, kLabelValues, kOptionalLabelKeys,
kOptionalLabelValues),
HistogramResultEq(kSum, kMin, kMax, kCount))))));
}
TEST_F(OpenTelemetryPluginNPCMetricsTest,
DisabledOptionalLabelKeysShouldNotBeRecorded) {
constexpr absl::string_view kMetricName =
"yet_another_yet_another_double_histogram";
constexpr double kHistogramValues[] = {1.1, 1.2, 2.2, 3.3,
4.4, 4.5, 5.5, 6.6};
constexpr double kSum = 28.8;
constexpr double kMin = 1.1;
constexpr double kMax = 6.6;
constexpr double kCount = 8;
constexpr std::array<absl::string_view, 2> kLabelKeys = {"label_key_1",
"label_key_2"};
constexpr std::array<absl::string_view, 4> kOptionalLabelKeys = {
"optional_label_key_1", "optional_label_key_2", "optional_label_key_3",
"optional_label_key_4"};
constexpr std::array<absl::string_view, 2> kActualOptionalLabelKeys = {
"optional_label_key_1", "optional_label_key_2"};
constexpr std::array<absl::string_view, 2> kLabelValues = {"label_value_1",
"label_value_2"};
constexpr std::array<absl::string_view, 4> kOptionalLabelValues = {
"optional_label_value_1", "optional_label_value_2",
"optional_label_value_3", "optional_label_value_4"};
constexpr std::array<absl::string_view, 2> kActualOptionalLabelValues = {
"optional_label_value_1", "optional_label_value_2"};
auto handle = grpc_core::GlobalInstrumentsRegistry::RegisterDoubleHistogram(
kMetricName, "A simple double histogram.", "unit", kLabelKeys,
kOptionalLabelKeys, /*enable_by_default=*/true);
Init(std::move(
Options()
.set_metric_names({kMetricName})
.set_server_selector([](const grpc_core::ChannelArgs& args) {
return args.GetString(GRPC_ARG_SERVER_SELECTOR_KEY) ==
GRPC_ARG_SERVER_SELECTOR_VALUE;
})
.add_optional_label(kOptionalLabelKeys[0])
.add_optional_label(kOptionalLabelKeys[1])));
grpc_core::ChannelArgs args;
args = args.Set(GRPC_ARG_SERVER_SELECTOR_KEY, GRPC_ARG_SERVER_SELECTOR_VALUE);
auto stats_plugins =
grpc_core::GlobalStatsPluginRegistry::GetStatsPluginsForServer(args);
for (auto v : kHistogramValues) {
stats_plugins.RecordHistogram(handle, v, kLabelValues,
kOptionalLabelValues);
}
auto data = ReadCurrentMetricsData(
[&](const absl::flat_hash_map<
std::string,
std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>&
data) { return !data.contains(kMetricName); });
EXPECT_THAT(
data,
::testing::ElementsAre(::testing::Pair(
kMetricName,
::testing::ElementsAre(::testing::AllOf(
AttributesEq(kLabelKeys, kLabelValues, kActualOptionalLabelKeys,
kActualOptionalLabelValues),
HistogramResultEq(kSum, kMin, kMax, kCount))))));
}
} // namespace
} // namespace testing
} // namespace grpc

View File

@ -32,6 +32,7 @@
#include "src/core/lib/channel/promise_based_filter.h"
#include "src/core/lib/config/core_configuration.h"
#include "src/core/lib/gprpp/notification.h"
#include "test/core/util/fake_stats_plugin.h"
#include "test/core/util/test_config.h"
#include "test/cpp/end2end/test_service_impl.h"
#include "test/cpp/util/byte_buffer_proto_helper.h"
@ -83,38 +84,7 @@ const grpc_channel_filter AddServiceLabelsFilter::kFilter =
"add_service_labels_filter");
void OpenTelemetryPluginEnd2EndTest::Init(Options config) {
// We are resetting the MeterProvider and OpenTelemetry plugin at the start
// of each test to avoid test results from one test carrying over to another
// test. (Some measurements can get arbitrarily delayed.)
auto meter_provider =
std::make_shared<opentelemetry::sdk::metrics::MeterProvider>(
std::make_unique<opentelemetry::sdk::metrics::ViewRegistry>(),
*config.resource);
reader_.reset(new grpc::testing::MockMetricReader);
meter_provider->AddMetricReader(reader_);
grpc_core::CoreConfiguration::Reset();
grpc::internal::OpenTelemetryPluginBuilderImpl ot_builder;
ot_builder.DisableAllMetrics();
for (const auto& metric_name : config.metric_names) {
ot_builder.EnableMetric(metric_name);
}
if (config.use_meter_provider) {
auto meter_provider =
std::make_shared<opentelemetry::sdk::metrics::MeterProvider>();
reader_.reset(new grpc::testing::MockMetricReader);
meter_provider->AddMetricReader(reader_);
ot_builder.SetMeterProvider(std::move(meter_provider));
}
ot_builder.SetTargetSelector(std::move(config.target_selector));
ot_builder.SetServerSelector(std::move(config.server_selector));
ot_builder.SetTargetAttributeFilter(
std::move(config.target_attribute_filter));
ot_builder.SetGenericMethodAttributeFilter(
std::move(config.generic_method_attribute_filter));
for (auto& option : config.plugin_options) {
ot_builder.AddPluginOption(std::move(option));
}
ASSERT_EQ(ot_builder.BuildAndRegisterGlobal(), absl::OkStatus());
ChannelArguments channel_args;
if (!config.labels_to_inject.empty()) {
labels_to_inject_ = config.labels_to_inject;
@ -125,6 +95,7 @@ void OpenTelemetryPluginEnd2EndTest::Init(Options config) {
});
channel_args.SetPointer(GRPC_ARG_LABELS_TO_INJECT, &labels_to_inject_);
}
reader_ = BuildAndRegisterOpenTelemetryPlugin(std::move(config));
grpc_init();
grpc::ServerBuilder builder;
int port;
@ -148,6 +119,8 @@ void OpenTelemetryPluginEnd2EndTest::TearDown() {
server_->Shutdown();
grpc_shutdown_blocking();
grpc_core::ServerCallTracerFactory::TestOnlyReset();
grpc_core::GlobalStatsPluginRegistryTestPeer::
ResetGlobalStatsPluginRegistry();
}
void OpenTelemetryPluginEnd2EndTest::ResetStub(
@ -183,14 +156,18 @@ OpenTelemetryPluginEnd2EndTest::ReadCurrentMetricsData(
bool(const absl::flat_hash_map<
std::string,
std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>&)>
continue_predicate) {
continue_predicate,
opentelemetry::sdk::metrics::MetricReader* reader) {
if (reader == nullptr) {
reader = reader_.get();
}
absl::flat_hash_map<
std::string,
std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>
data;
auto deadline = absl::Now() + absl::Seconds(5);
do {
reader_->Collect([&](opentelemetry::sdk::metrics::ResourceMetrics& rm) {
reader->Collect([&](opentelemetry::sdk::metrics::ResourceMetrics& rm) {
for (const opentelemetry::sdk::metrics::ScopeMetrics& smd :
rm.scope_metric_data_) {
for (const opentelemetry::sdk::metrics::MetricData& md :
@ -207,5 +184,46 @@ OpenTelemetryPluginEnd2EndTest::ReadCurrentMetricsData(
return data;
}
std::shared_ptr<opentelemetry::sdk::metrics::MetricReader>
OpenTelemetryPluginEnd2EndTest::BuildAndRegisterOpenTelemetryPlugin(
OpenTelemetryPluginEnd2EndTest::Options options) {
grpc::internal::OpenTelemetryPluginBuilderImpl ot_builder;
// We are resetting the MeterProvider and OpenTelemetry plugin at the start
// of each test to avoid test results from one test carrying over to another
// test. (Some measurements can get arbitrarily delayed.)
auto meter_provider =
std::make_shared<opentelemetry::sdk::metrics::MeterProvider>(
std::make_unique<opentelemetry::sdk::metrics::ViewRegistry>(),
*options.resource);
std::shared_ptr<opentelemetry::sdk::metrics::MetricReader> reader =
std::make_shared<grpc::testing::MockMetricReader>();
meter_provider->AddMetricReader(reader);
ot_builder.DisableAllMetrics();
for (const auto& metric_name : options.metric_names) {
ot_builder.EnableMetric(metric_name);
}
if (options.use_meter_provider) {
auto meter_provider =
std::make_shared<opentelemetry::sdk::metrics::MeterProvider>();
reader.reset(new grpc::testing::MockMetricReader);
meter_provider->AddMetricReader(reader);
ot_builder.SetMeterProvider(std::move(meter_provider));
}
ot_builder.SetTargetSelector(std::move(options.target_selector));
ot_builder.SetServerSelector(std::move(options.server_selector));
ot_builder.SetTargetAttributeFilter(
std::move(options.target_attribute_filter));
ot_builder.SetGenericMethodAttributeFilter(
std::move(options.generic_method_attribute_filter));
for (auto& option : options.plugin_options) {
ot_builder.AddPluginOption(std::move(option));
}
for (auto& optional_label_key : options.optional_label_keys) {
ot_builder.AddOptionalLabel(optional_label_key);
}
EXPECT_EQ(ot_builder.BuildAndRegisterGlobal(), absl::OkStatus());
return reader;
}
} // namespace testing
} // namespace grpc

View File

@ -114,6 +114,11 @@ class OpenTelemetryPluginEnd2EndTest : public ::testing::Test {
return *this;
}
Options& add_optional_label(absl::string_view optional_label_key) {
optional_label_keys.emplace(optional_label_key);
return *this;
}
absl::flat_hash_set<absl::string_view> metric_names;
// TODO(yashykt): opentelemetry::sdk::resource::Resource doesn't have a copy
// assignment operator so wrapping it in a unique_ptr till it is fixed.
@ -135,6 +140,7 @@ class OpenTelemetryPluginEnd2EndTest : public ::testing::Test {
std::vector<
std::unique_ptr<grpc::internal::InternalOpenTelemetryPluginOption>>
plugin_options;
absl::flat_hash_set<absl::string_view> optional_label_keys;
};
// Note that we can't use SetUp() here since we want to send in parameters.
@ -147,6 +153,10 @@ class OpenTelemetryPluginEnd2EndTest : public ::testing::Test {
void SendRPC();
void SendGenericRPC();
std::shared_ptr<opentelemetry::sdk::metrics::MetricReader>
BuildAndRegisterOpenTelemetryPlugin(
OpenTelemetryPluginEnd2EndTest::Options options);
absl::flat_hash_map<
std::string,
std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>
@ -155,7 +165,8 @@ class OpenTelemetryPluginEnd2EndTest : public ::testing::Test {
bool(const absl::flat_hash_map<
std::string,
std::vector<opentelemetry::sdk::metrics::PointDataAttributes>>&)>
continue_predicate);
continue_predicate,
opentelemetry::sdk::metrics::MetricReader* reader = nullptr);
const absl::string_view kMethodName = "grpc.testing.EchoTestService/Echo";
const absl::string_view kGenericMethodName = "foo/bar";

View File

@ -2165,6 +2165,7 @@ src/core/lib/channel/metrics.h \
src/core/lib/channel/promise_based_filter.cc \
src/core/lib/channel/promise_based_filter.h \
src/core/lib/channel/server_call_tracer_filter.cc \
src/core/lib/channel/server_call_tracer_filter.h \
src/core/lib/channel/status_util.cc \
src/core/lib/channel/status_util.h \
src/core/lib/channel/tcp_tracer.h \

View File

@ -1937,6 +1937,7 @@ src/core/lib/channel/metrics.h \
src/core/lib/channel/promise_based_filter.cc \
src/core/lib/channel/promise_based_filter.h \
src/core/lib/channel/server_call_tracer_filter.cc \
src/core/lib/channel/server_call_tracer_filter.h \
src/core/lib/channel/status_util.cc \
src/core/lib/channel/status_util.h \
src/core/lib/channel/tcp_tracer.h \