pull/36118/head
Craig Tiller 10 months ago
commit 68e0acd0a2
  1. 61
      BUILD
  2. 152
      CMakeLists.txt
  3. 3
      Makefile
  4. 7
      Package.swift
  5. 33
      bazel/experiments.bzl
  6. 7
      bazel/grpc_build_system.bzl
  7. 247
      build_autogenerated.yaml
  8. 3
      config.m4
  9. 3
      config.w32
  10. 10
      doc/grpc_xds_features.md
  11. 8
      gRPC-C++.podspec
  12. 11
      gRPC-Core.podspec
  13. 7
      grpc.gemspec
  14. 10
      include/grpcpp/ext/otel_plugin.h
  15. 9
      include/grpcpp/impl/server_callback_handlers.h
  16. 9
      include/grpcpp/server_context.h
  17. 9
      include/grpcpp/support/server_callback.h
  18. 7
      package.xml
  19. 33
      src/core/BUILD
  20. 10
      src/core/client_channel/client_channel_filter.cc
  21. 11
      src/core/client_channel/http_proxy_mapper.cc
  22. 50
      src/core/ext/filters/http/http_filters_plugin.cc
  23. 328
      src/core/ext/filters/http/message_compress/legacy_compression_filter.cc
  24. 140
      src/core/ext/filters/http/message_compress/legacy_compression_filter.h
  25. 1
      src/core/ext/filters/server_config_selector/server_config_selector_filter.cc
  26. 27
      src/core/ext/transport/chaotic_good/chaotic_good_transport.h
  27. 4
      src/core/ext/transport/chaotic_good/client/chaotic_good_connector.cc
  28. 8
      src/core/ext/transport/chaotic_good/server/chaotic_good_server.cc
  29. 1
      src/core/ext/transport/inproc/inproc_transport.cc
  30. 2
      src/core/ext/xds/xds_client_grpc.cc
  31. 3
      src/core/lib/channel/call_tracer.h
  32. 139
      src/core/lib/channel/metrics.cc
  33. 201
      src/core/lib/channel/metrics.h
  34. 4
      src/core/lib/channel/promise_based_filter.h
  35. 2
      src/core/lib/channel/server_call_tracer_filter.cc
  36. 28
      src/core/lib/channel/server_call_tracer_filter.h
  37. 6
      src/core/lib/event_engine/default_event_engine.h
  38. 31
      src/core/lib/event_engine/event_engine_context.h
  39. 20
      src/core/lib/event_engine/extensions/chaotic_good_extension.h
  40. 108
      src/core/lib/experiments/config.cc
  41. 84
      src/core/lib/experiments/experiments.cc
  42. 38
      src/core/lib/experiments/experiments.h
  43. 37
      src/core/lib/experiments/experiments.yaml
  44. 4
      src/core/lib/experiments/rollouts.yaml
  45. 1
      src/core/lib/promise/activity.h
  46. 2
      src/core/lib/promise/sleep.cc
  47. 20
      src/core/lib/security/credentials/jwt/json_token.cc
  48. 41
      src/core/lib/security/credentials/jwt/jwt_verifier.cc
  49. 25
      src/core/lib/security/transport/auth_filters.h
  50. 244
      src/core/lib/security/transport/legacy_server_auth_filter.cc
  51. 239
      src/core/lib/slice/b64.cc
  52. 52
      src/core/lib/slice/b64.h
  53. 36
      src/core/lib/slice/slice.cc
  54. 60
      src/core/lib/slice/slice_buffer.cc
  55. 15
      src/core/lib/slice/slice_buffer.h
  56. 7
      src/core/lib/slice/slice_internal.h
  57. 25
      src/core/lib/surface/call.cc
  58. 15
      src/core/lib/surface/init.cc
  59. 17
      src/core/lib/surface/legacy_channel.cc
  60. 35
      src/core/lib/surface/server.cc
  61. 48
      src/core/lib/transport/promise_endpoint.h
  62. 2
      src/core/plugin_registry/grpc_plugin_registry.cc
  63. 8
      src/cpp/client/client_callback.cc
  64. 6
      src/cpp/ext/otel/BUILD
  65. 23
      src/cpp/ext/otel/key_value_iterable.h
  66. 282
      src/cpp/ext/otel/otel_client_call_tracer.cc
  67. 35
      src/cpp/ext/otel/otel_client_call_tracer.h
  68. 328
      src/cpp/ext/otel/otel_client_filter.cc
  69. 68
      src/cpp/ext/otel/otel_client_filter.h
  70. 461
      src/cpp/ext/otel/otel_plugin.cc
  71. 298
      src/cpp/ext/otel/otel_plugin.h
  72. 198
      src/cpp/ext/otel/otel_server_call_tracer.cc
  73. 109
      src/cpp/ext/otel/otel_server_call_tracer.h
  74. 59
      src/cpp/server/server_callback.cc
  75. 2
      src/objective-c/BUILD
  76. 12
      src/objective-c/BoringSSL-GRPC.podspec
  77. 8
      src/objective-c/PrivacyInfo.xcprivacy
  78. 6
      src/objective-c/examples/BUILD
  79. 10
      src/objective-c/grpc_objc_internal_library.bzl
  80. 6
      src/objective-c/tests/BUILD
  81. 2
      src/proto/grpc/testing/BUILD
  82. 2
      src/proto/grpc/testing/xds/v3/BUILD
  83. 3
      src/python/grpcio/grpc_core_dependencies.py
  84. 3
      src/python/grpcio_tests/tests/stress/BUILD.bazel
  85. 2
      test/core/client_channel/lb_policy/pick_first_test.cc
  86. 2
      test/core/client_channel/lb_policy/weighted_round_robin_test.cc
  87. 0
      test/core/end2end/end2end_test_corpus/retry_streaming/clusterfuzz-testcase-minimized-retry_streaming_fuzzer-6651400812036096
  88. 2
      test/core/end2end/grpc_core_end2end_test.bzl
  89. 52
      test/core/end2end/tests/http2_stats.cc
  90. 2
      test/core/gprpp/BUILD
  91. 2
      test/core/iomgr/BUILD
  92. 2
      test/core/security/alts_security_connector_test.cc
  93. 37
      test/core/slice/BUILD
  94. 6
      test/core/slice/b64_decode_corpus/testcase-5759629707444224
  95. 39
      test/core/slice/b64_decode_fuzzer.cc
  96. 1
      test/core/slice/b64_encode_corpus/testcase-5686577615339520
  97. 37
      test/core/slice/b64_encode_fuzzer.cc
  98. 193
      test/core/slice/b64_test.cc
  99. 1
      test/core/transport/chaotic_good/client_transport_error_test.cc
  100. 1
      test/core/transport/chaotic_good/client_transport_test.cc
  101. Some files were not shown because too many files have changed in this diff Show More

61
BUILD

@ -14,6 +14,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
load("@bazel_skylib//lib:selects.bzl", "selects")
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
load(
"//bazel:grpc_build_system.bzl",
"grpc_cc_library",
@ -22,8 +24,6 @@ load(
"grpc_upb_proto_reflection_library",
"python_config_settings",
)
load("@bazel_skylib//lib:selects.bzl", "selects")
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
licenses(["reciprocal"])
@ -1695,7 +1695,6 @@ grpc_cc_library(
language = "c++",
visibility = ["@grpc:alt_grpc_base_legacy"],
deps = [
"config",
"gpr",
"legacy_context",
"tcp_tracer",
@ -1920,7 +1919,6 @@ grpc_cc_library(
"//src/core:lib/channel/promise_based_filter.cc",
"//src/core:lib/channel/status_util.cc",
"//src/core:lib/compression/message_compress.cc",
"//src/core:lib/slice/b64.cc",
"//src/core:lib/surface/call.cc",
"//src/core:lib/surface/call_details.cc",
"//src/core:lib/surface/call_log_batch.cc",
@ -1943,7 +1941,6 @@ grpc_cc_library(
"//src/core:lib/channel/promise_based_filter.h",
"//src/core:lib/channel/status_util.h",
"//src/core:lib/compression/message_compress.h",
"//src/core:lib/slice/b64.h",
"//src/core:lib/surface/call.h",
"//src/core:lib/surface/call_test_only.h",
"//src/core:lib/surface/completion_queue.h",
@ -1962,20 +1959,15 @@ grpc_cc_library(
}),
external_deps = [
"absl/base:core_headers",
"absl/cleanup",
"absl/container:flat_hash_map",
"absl/container:flat_hash_set",
"absl/container:inlined_vector",
"absl/functional:any_invocable",
"absl/functional:function_ref",
"absl/hash",
"absl/meta:type_traits",
"absl/random",
"absl/status",
"absl/status:statusor",
"absl/strings",
"absl/strings:str_format",
"absl/time",
"absl/types:optional",
"absl/utility",
"madler_zlib",
@ -1989,7 +1981,6 @@ grpc_cc_library(
visibility = ["@grpc:alt_grpc_base_legacy"],
deps = [
"api_trace",
"byte_buffer",
"call_combiner",
"call_trace",
"call_tracer",
@ -1998,28 +1989,19 @@ grpc_cc_library(
"channel_stack_builder",
"channelz",
"config",
"config_vars",
"cpp_impl_of",
"debug_location",
"dynamic_annotations",
"exec_ctx",
"gpr",
"grpc_public_hdrs",
"grpc_trace",
"iomgr",
"iomgr_buffer_list",
"iomgr_internal_errqueue",
"iomgr_timer",
"legacy_context",
"orphanable",
"parse_address",
"promise",
"ref_counted_ptr",
"resource_quota_api",
"sockaddr_utils",
"stats",
"tcp_tracer",
"uri_parser",
"//src/core:1999",
"//src/core:activity",
"//src/core:all_ok",
@ -2027,14 +2009,11 @@ grpc_cc_library(
"//src/core:arena_promise",
"//src/core:atomic_utils",
"//src/core:bitset",
"//src/core:call_factory",
"//src/core:call_filters",
"//src/core:call_final_info",
"//src/core:call_finalization",
"//src/core:call_spine",
"//src/core:cancel_callback",
"//src/core:channel_args",
"//src/core:channel_args_endpoint_config",
"//src/core:channel_args_preconditioning",
"//src/core:channel_fwd",
"//src/core:channel_init",
@ -2043,75 +2022,47 @@ grpc_cc_library(
"//src/core:closure",
"//src/core:compression",
"//src/core:connectivity_state",
"//src/core:construct_destruct",
"//src/core:context",
"//src/core:default_event_engine",
"//src/core:dual_ref_counted",
"//src/core:error",
"//src/core:error_utils",
"//src/core:event_engine_common",
"//src/core:event_engine_extensions",
"//src/core:event_engine_memory_allocator_factory",
"//src/core:event_engine_query_extensions",
"//src/core:event_engine_shim",
"//src/core:event_engine_tcp_socket_utils",
"//src/core:event_engine_trace",
"//src/core:event_log",
"//src/core:event_engine_context",
"//src/core:experiments",
"//src/core:for_each",
"//src/core:gpr_atm",
"//src/core:gpr_manual_constructor",
"//src/core:gpr_spinlock",
"//src/core:grpc_sockaddr",
"//src/core:if",
"//src/core:init_internally",
"//src/core:iomgr_fwd",
"//src/core:iomgr_port",
"//src/core:json",
"//src/core:json_writer",
"//src/core:latch",
"//src/core:loop",
"//src/core:map",
"//src/core:match",
"//src/core:memory_quota",
"//src/core:message",
"//src/core:metadata",
"//src/core:metadata_batch",
"//src/core:metrics",
"//src/core:no_destruct",
"//src/core:per_cpu",
"//src/core:pipe",
"//src/core:poll",
"//src/core:pollset_set",
"//src/core:posix_event_engine_base_hdrs",
"//src/core:posix_event_engine_endpoint",
"//src/core:promise_status",
"//src/core:promise_trace",
"//src/core:race",
"//src/core:random_early_detection",
"//src/core:ref_counted",
"//src/core:resolved_address",
"//src/core:resource_quota",
"//src/core:resource_quota_trace",
"//src/core:seq",
"//src/core:server_interface",
"//src/core:slice",
"//src/core:slice_buffer",
"//src/core:slice_cast",
"//src/core:slice_refcount",
"//src/core:socket_mutator",
"//src/core:stats_data",
"//src/core:status_flag",
"//src/core:status_helper",
"//src/core:strerror",
"//src/core:thread_quota",
"//src/core:time",
"//src/core:transport_fwd",
"//src/core:try_join",
"//src/core:try_seq",
"//src/core:useful",
"//src/core:windows_event_engine",
"//src/core:windows_event_engine_listener",
],
)
@ -2260,7 +2211,6 @@ grpc_cc_library(
"//src/core:lib/security/credentials/plugin/plugin_credentials.cc",
"//src/core:lib/security/security_connector/security_connector.cc",
"//src/core:lib/security/transport/client_auth_filter.cc",
"//src/core:lib/security/transport/legacy_server_auth_filter.cc",
"//src/core:lib/security/transport/secure_endpoint.cc",
"//src/core:lib/security/transport/security_handshaker.cc",
"//src/core:lib/security/transport/server_auth_filter.cc",
@ -2435,6 +2385,7 @@ grpc_cc_library(
],
external_deps = [
"absl/base:core_headers",
"absl/functional:any_invocable",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -2515,6 +2466,7 @@ grpc_cc_library(
hdrs = GRPCXX_HDRS,
external_deps = [
"absl/base:core_headers",
"absl/functional:any_invocable",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -3969,7 +3921,6 @@ grpc_cc_library(
"//src/core:arena_promise",
"//src/core:closure",
"//src/core:error",
"//src/core:experiments",
"//src/core:gpr_manual_constructor",
"//src/core:httpcli_ssl_credentials",
"//src/core:iomgr_fwd",
@ -4187,13 +4138,11 @@ grpc_cc_library(
"//src/core:ext/filters/http/client/http_client_filter.cc",
"//src/core:ext/filters/http/http_filters_plugin.cc",
"//src/core:ext/filters/http/message_compress/compression_filter.cc",
"//src/core:ext/filters/http/message_compress/legacy_compression_filter.cc",
"//src/core:ext/filters/http/server/http_server_filter.cc",
],
hdrs = [
"//src/core:ext/filters/http/client/http_client_filter.h",
"//src/core:ext/filters/http/message_compress/compression_filter.h",
"//src/core:ext/filters/http/message_compress/legacy_compression_filter.h",
"//src/core:ext/filters/http/server/http_server_filter.h",
],
external_deps = [

152
CMakeLists.txt generated

@ -930,7 +930,6 @@ if(gRPC_BUILD_TESTS)
add_dependencies(buildtests_cxx authorization_policy_provider_test)
add_dependencies(buildtests_cxx avl_test)
add_dependencies(buildtests_cxx aws_request_signer_test)
add_dependencies(buildtests_cxx b64_test)
add_dependencies(buildtests_cxx backend_metrics_lb_policy_test)
add_dependencies(buildtests_cxx backoff_test)
add_dependencies(buildtests_cxx bad_ping_test)
@ -1844,7 +1843,6 @@ add_library(grpc
src/core/ext/filters/http/client_authority_filter.cc
src/core/ext/filters/http/http_filters_plugin.cc
src/core/ext/filters/http/message_compress/compression_filter.cc
src/core/ext/filters/http/message_compress/legacy_compression_filter.cc
src/core/ext/filters/http/server/http_server_filter.cc
src/core/ext/filters/message_size/message_size_filter.cc
src/core/ext/filters/rbac/rbac_filter.cc
@ -2478,13 +2476,11 @@ add_library(grpc
src/core/lib/security/security_connector/ssl_utils.cc
src/core/lib/security/security_connector/tls/tls_security_connector.cc
src/core/lib/security/transport/client_auth_filter.cc
src/core/lib/security/transport/legacy_server_auth_filter.cc
src/core/lib/security/transport/secure_endpoint.cc
src/core/lib/security/transport/security_handshaker.cc
src/core/lib/security/transport/server_auth_filter.cc
src/core/lib/security/transport/tsi_error.cc
src/core/lib/security/util/json_util.cc
src/core/lib/slice/b64.cc
src/core/lib/slice/percent_encoding.cc
src/core/lib/slice/slice.cc
src/core/lib/slice/slice_buffer.cc
@ -2943,7 +2939,6 @@ add_library(grpc_unsecure
src/core/ext/filters/http/client_authority_filter.cc
src/core/ext/filters/http/http_filters_plugin.cc
src/core/ext/filters/http/message_compress/compression_filter.cc
src/core/ext/filters/http/message_compress/legacy_compression_filter.cc
src/core/ext/filters/http/server/http_server_filter.cc
src/core/ext/filters/message_size/message_size_filter.cc
src/core/ext/transport/chttp2/client/chttp2_connector.cc
@ -3207,13 +3202,11 @@ add_library(grpc_unsecure
src/core/lib/security/security_connector/load_system_roots_windows.cc
src/core/lib/security/security_connector/security_connector.cc
src/core/lib/security/transport/client_auth_filter.cc
src/core/lib/security/transport/legacy_server_auth_filter.cc
src/core/lib/security/transport/secure_endpoint.cc
src/core/lib/security/transport/security_handshaker.cc
src/core/lib/security/transport/server_auth_filter.cc
src/core/lib/security/transport/tsi_error.cc
src/core/lib/security/util/json_util.cc
src/core/lib/slice/b64.cc
src/core/lib/slice/percent_encoding.cc
src/core/lib/slice/slice.cc
src/core/lib/slice/slice_buffer.cc
@ -5116,7 +5109,6 @@ add_library(grpc_authorization_provider
src/core/lib/address_utils/parse_address.cc
src/core/lib/address_utils/sockaddr_utils.cc
src/core/lib/backoff/backoff.cc
src/core/lib/backoff/random_early_detection.cc
src/core/lib/channel/call_tracer.cc
src/core/lib/channel/channel_args.cc
src/core/lib/channel/channel_args_preconditioning.cc
@ -5318,13 +5310,11 @@ add_library(grpc_authorization_provider
src/core/lib/security/security_connector/load_system_roots_windows.cc
src/core/lib/security/security_connector/security_connector.cc
src/core/lib/security/transport/client_auth_filter.cc
src/core/lib/security/transport/legacy_server_auth_filter.cc
src/core/lib/security/transport/secure_endpoint.cc
src/core/lib/security/transport/security_handshaker.cc
src/core/lib/security/transport/server_auth_filter.cc
src/core/lib/security/transport/tsi_error.cc
src/core/lib/security/util/json_util.cc
src/core/lib/slice/b64.cc
src/core/lib/slice/percent_encoding.cc
src/core/lib/slice/slice.cc
src/core/lib/slice/slice_buffer.cc
@ -5349,10 +5339,8 @@ add_library(grpc_authorization_provider
src/core/lib/surface/version.cc
src/core/lib/surface/wait_for_cq_end_op.cc
src/core/lib/transport/batch_builder.cc
src/core/lib/transport/call_factory.cc
src/core/lib/transport/call_filters.cc
src/core/lib/transport/call_final_info.cc
src/core/lib/transport/call_size_estimator.cc
src/core/lib/transport/call_spine.cc
src/core/lib/transport/connectivity_state.cc
src/core/lib/transport/error_utils.cc
@ -5442,8 +5430,6 @@ target_link_libraries(grpc_authorization_provider
absl::function_ref
absl::hash
absl::type_traits
absl::random_bit_gen_ref
absl::random_distributions
absl::statusor
absl::span
absl::utility
@ -5700,7 +5686,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
)
@ -7400,48 +7386,6 @@ target_link_libraries(aws_request_signer_test
)
endif()
if(gRPC_BUILD_TESTS)
add_executable(b64_test
test/core/slice/b64_test.cc
)
if(WIN32 AND MSVC)
if(BUILD_SHARED_LIBS)
target_compile_definitions(b64_test
PRIVATE
"GPR_DLL_IMPORTS"
"GRPC_DLL_IMPORTS"
)
endif()
endif()
target_compile_features(b64_test PUBLIC cxx_std_14)
target_include_directories(b64_test
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
${_gRPC_RE2_INCLUDE_DIR}
${_gRPC_SSL_INCLUDE_DIR}
${_gRPC_UPB_GENERATED_DIR}
${_gRPC_UPB_GRPC_GENERATED_DIR}
${_gRPC_UPB_INCLUDE_DIR}
${_gRPC_XXHASH_INCLUDE_DIR}
${_gRPC_ZLIB_INCLUDE_DIR}
third_party/googletest/googletest/include
third_party/googletest/googletest
third_party/googletest/googlemock/include
third_party/googletest/googlemock
${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(b64_test
${_gRPC_ALLTARGETS_LIBRARIES}
gtest
grpc_test_util
)
endif()
if(gRPC_BUILD_TESTS)
@ -7565,6 +7509,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)
@ -8040,6 +7985,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)
@ -8479,6 +8425,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)
@ -8685,6 +8632,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)
@ -8790,6 +8738,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)
@ -8852,6 +8801,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)
@ -8914,6 +8864,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)
@ -8976,6 +8927,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)
@ -9085,6 +9037,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)
@ -9189,6 +9142,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)
@ -9251,6 +9205,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)
@ -10897,6 +10852,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)
@ -11235,6 +11191,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)
@ -11519,6 +11476,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)
@ -11947,6 +11905,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)
@ -12154,6 +12113,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)
@ -12473,6 +12433,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)
@ -13849,6 +13810,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)
@ -13911,6 +13873,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)
@ -13973,6 +13936,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)
@ -14085,6 +14049,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)
@ -14873,6 +14838,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)
@ -15238,6 +15204,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)
@ -16628,6 +16595,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)
@ -16936,6 +16904,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)
@ -17091,6 +17060,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)
@ -17983,6 +17953,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)
@ -18371,6 +18342,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)
@ -18476,6 +18448,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)
@ -19148,6 +19121,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)
@ -19210,6 +19184,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)
@ -19272,6 +19247,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)
@ -19334,6 +19310,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)
@ -20015,6 +19992,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)
@ -20109,6 +20087,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)
@ -20171,6 +20150,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)
@ -20638,9 +20618,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
@ -21098,6 +21079,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)
@ -21472,6 +21454,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)
@ -21585,6 +21568,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)
@ -22578,6 +22562,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)
@ -23153,6 +23138,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)
@ -23259,6 +23245,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)
@ -23321,6 +23308,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)
@ -23654,6 +23642,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)
@ -23758,6 +23747,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)
@ -23820,6 +23810,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)
@ -23882,6 +23873,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)
@ -23944,6 +23936,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)
@ -24006,6 +23999,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)
@ -24068,6 +24062,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)
@ -24130,6 +24125,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)
@ -24192,6 +24188,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)
@ -24254,6 +24251,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)
@ -24316,6 +24314,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)
@ -24378,6 +24377,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)
@ -24440,6 +24440,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)
@ -24502,6 +24503,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)
@ -24564,6 +24566,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)
@ -24626,6 +24629,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)
@ -24688,6 +24692,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)
@ -24750,6 +24755,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)
@ -24812,6 +24818,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)
@ -24874,6 +24881,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)
@ -24936,6 +24944,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)
@ -24998,6 +25007,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)
@ -25060,6 +25070,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)
@ -25122,6 +25133,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)
@ -25226,6 +25238,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)
@ -25288,6 +25301,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)
@ -25350,6 +25364,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)
@ -25412,6 +25427,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)
@ -25516,6 +25532,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)
@ -25578,6 +25595,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)
@ -25640,6 +25658,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)
@ -25702,6 +25721,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)
@ -25764,6 +25784,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)
@ -25826,6 +25847,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)
@ -25888,6 +25910,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)
@ -26871,6 +26894,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)
@ -27154,6 +27178,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)
@ -27415,6 +27440,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)
@ -27477,6 +27503,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)
@ -27602,6 +27629,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)
@ -27664,6 +27692,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)
@ -27770,6 +27799,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)
@ -28695,6 +28725,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)
@ -29426,6 +29457,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)
@ -30684,6 +30716,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)
@ -31187,6 +31220,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)
@ -32422,6 +32456,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)
@ -32484,6 +32519,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)

3
Makefile generated

@ -696,7 +696,6 @@ LIBGRPC_SRC = \
src/core/ext/filters/http/client_authority_filter.cc \
src/core/ext/filters/http/http_filters_plugin.cc \
src/core/ext/filters/http/message_compress/compression_filter.cc \
src/core/ext/filters/http/message_compress/legacy_compression_filter.cc \
src/core/ext/filters/http/server/http_server_filter.cc \
src/core/ext/filters/message_size/message_size_filter.cc \
src/core/ext/filters/rbac/rbac_filter.cc \
@ -1375,13 +1374,11 @@ LIBGRPC_SRC = \
src/core/lib/security/security_connector/ssl_utils.cc \
src/core/lib/security/security_connector/tls/tls_security_connector.cc \
src/core/lib/security/transport/client_auth_filter.cc \
src/core/lib/security/transport/legacy_server_auth_filter.cc \
src/core/lib/security/transport/secure_endpoint.cc \
src/core/lib/security/transport/security_handshaker.cc \
src/core/lib/security/transport/server_auth_filter.cc \
src/core/lib/security/transport/tsi_error.cc \
src/core/lib/security/util/json_util.cc \
src/core/lib/slice/b64.cc \
src/core/lib/slice/percent_encoding.cc \
src/core/lib/slice/slice.cc \
src/core/lib/slice/slice_buffer.cc \

7
Package.swift generated

@ -176,8 +176,6 @@ let package = Package(
"src/core/ext/filters/http/http_filters_plugin.cc",
"src/core/ext/filters/http/message_compress/compression_filter.cc",
"src/core/ext/filters/http/message_compress/compression_filter.h",
"src/core/ext/filters/http/message_compress/legacy_compression_filter.cc",
"src/core/ext/filters/http/message_compress/legacy_compression_filter.h",
"src/core/ext/filters/http/server/http_server_filter.cc",
"src/core/ext/filters/http/server/http_server_filter.h",
"src/core/ext/filters/message_size/message_size_filter.cc",
@ -1160,6 +1158,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",
@ -1202,6 +1201,7 @@ let package = Package(
"src/core/lib/event_engine/default_event_engine_factory.cc",
"src/core/lib/event_engine/default_event_engine_factory.h",
"src/core/lib/event_engine/event_engine.cc",
"src/core/lib/event_engine/event_engine_context.h",
"src/core/lib/event_engine/extensions/can_track_errors.h",
"src/core/lib/event_engine/extensions/chaotic_good_extension.h",
"src/core/lib/event_engine/extensions/supports_fd.h",
@ -1740,7 +1740,6 @@ let package = Package(
"src/core/lib/security/security_connector/tls/tls_security_connector.h",
"src/core/lib/security/transport/auth_filters.h",
"src/core/lib/security/transport/client_auth_filter.cc",
"src/core/lib/security/transport/legacy_server_auth_filter.cc",
"src/core/lib/security/transport/secure_endpoint.cc",
"src/core/lib/security/transport/secure_endpoint.h",
"src/core/lib/security/transport/security_handshaker.cc",
@ -1750,8 +1749,6 @@ let package = Package(
"src/core/lib/security/transport/tsi_error.h",
"src/core/lib/security/util/json_util.cc",
"src/core/lib/security/util/json_util.h",
"src/core/lib/slice/b64.cc",
"src/core/lib/slice/b64.h",
"src/core/lib/slice/percent_encoding.cc",
"src/core/lib/slice/percent_encoding.h",
"src/core/lib/slice/slice.cc",

@ -17,7 +17,6 @@
"""Dictionary of tags to experiments so we know when to test different experiments."""
EXPERIMENT_ENABLES = {
"absl_base64": "absl_base64",
"call_status_override_on_cancellation": "call_status_override_on_cancellation",
"call_v3": "call_v3",
"canary_client_privacy": "canary_client_privacy",
@ -36,8 +35,7 @@ EXPERIMENT_ENABLES = {
"promise_based_client_call": "event_engine_client,event_engine_listener,promise_based_client_call",
"promise_based_server_call": "promise_based_server_call",
"chaotic_good": "chaotic_good,event_engine_client,event_engine_listener,promise_based_client_call,promise_based_server_call",
"registered_method_lookup_in_transport": "registered_method_lookup_in_transport",
"promise_based_inproc_transport": "event_engine_client,event_engine_listener,promise_based_client_call,promise_based_inproc_transport,promise_based_server_call,registered_method_lookup_in_transport",
"promise_based_inproc_transport": "event_engine_client,event_engine_listener,promise_based_client_call,promise_based_inproc_transport,promise_based_server_call",
"rstpit": "rstpit",
"schedule_cancellation_over_write": "schedule_cancellation_over_write",
"server_privacy": "server_privacy",
@ -47,8 +45,6 @@ EXPERIMENT_ENABLES = {
"unconstrained_max_quota_buffer_size": "unconstrained_max_quota_buffer_size",
"v3_backend_metric_filter": "v3_backend_metric_filter",
"v3_channel_idle_filters": "v3_channel_idle_filters",
"v3_compression_filter": "v3_compression_filter",
"v3_server_auth_filter": "v3_server_auth_filter",
"work_serializer_clears_time_cache": "work_serializer_clears_time_cache",
"work_serializer_dispatch": "event_engine_client,work_serializer_dispatch",
}
@ -64,9 +60,6 @@ EXPERIMENTS = {
"dbg": {
},
"off": {
"compression_test": [
"v3_compression_filter",
],
"core_end2end_test": [
"promise_based_server_call",
],
@ -99,24 +92,15 @@ EXPERIMENTS = {
"core_end2end_test": [
"event_engine_listener",
],
"credential_token_tests": [
"absl_base64",
],
"event_engine_listener_test": [
"event_engine_listener",
],
"surface_registered_method_lookup": [
"registered_method_lookup_in_transport",
],
},
},
"ios": {
"dbg": {
},
"off": {
"compression_test": [
"v3_compression_filter",
],
"core_end2end_test": [
"promise_based_server_call",
],
@ -146,21 +130,12 @@ EXPERIMENTS = {
],
},
"on": {
"credential_token_tests": [
"absl_base64",
],
"surface_registered_method_lookup": [
"registered_method_lookup_in_transport",
],
},
},
"posix": {
"dbg": {
},
"off": {
"compression_test": [
"v3_compression_filter",
],
"core_end2end_test": [
"chaotic_good",
"event_engine_client",
@ -209,9 +184,6 @@ EXPERIMENTS = {
"cpp_end2end_test": [
"work_serializer_dispatch",
],
"credential_token_tests": [
"absl_base64",
],
"event_engine_listener_test": [
"event_engine_listener",
],
@ -221,9 +193,6 @@ EXPERIMENTS = {
"resolver_component_tests_runner_invoker": [
"event_engine_dns",
],
"surface_registered_method_lookup": [
"registered_method_lookup_in_transport",
],
"xds_end2end_test": [
"work_serializer_dispatch",
],

@ -27,13 +27,13 @@
Contains macros used throughout the repo.
"""
load("@build_bazel_rules_apple//apple:ios.bzl", "ios_unit_test")
load("@build_bazel_rules_apple//apple/testing/default_runner:ios_test_runner.bzl", "ios_test_runner")
load("@com_google_protobuf//bazel:upb_proto_library.bzl", "upb_proto_library", "upb_proto_reflection_library")
load("//bazel:cc_grpc_library.bzl", "cc_grpc_library")
load("//bazel:copts.bzl", "GRPC_DEFAULT_COPTS")
load("//bazel:experiments.bzl", "EXPERIMENTS", "EXPERIMENT_ENABLES", "EXPERIMENT_POLLERS")
load("//bazel:test_experiments.bzl", "TEST_EXPERIMENTS", "TEST_EXPERIMENT_ENABLES", "TEST_EXPERIMENT_POLLERS")
load("@build_bazel_rules_apple//apple:ios.bzl", "ios_unit_test")
load("@build_bazel_rules_apple//apple/testing/default_runner:ios_test_runner.bzl", "ios_test_runner")
load("@com_google_protobuf//bazel:upb_proto_library.bzl", "upb_proto_library", "upb_proto_reflection_library")
# The set of pollers to test against if a test exercises polling
POLLERS = ["epoll1", "poll"]
@ -120,6 +120,7 @@ def _update_visibility(visibility):
"tsi": PRIVATE,
"xds": PRIVATE,
"xds_client_core": PRIVATE,
"xds_end2end_test_utils": PRIVATE,
"grpc_python_observability": PRIVATE,
"event_engine_base_hdrs": PRIVATE,
"useful": PRIVATE,

File diff suppressed because it is too large Load Diff

3
config.m4 generated

@ -71,7 +71,6 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/filters/http/client_authority_filter.cc \
src/core/ext/filters/http/http_filters_plugin.cc \
src/core/ext/filters/http/message_compress/compression_filter.cc \
src/core/ext/filters/http/message_compress/legacy_compression_filter.cc \
src/core/ext/filters/http/server/http_server_filter.cc \
src/core/ext/filters/message_size/message_size_filter.cc \
src/core/ext/filters/rbac/rbac_filter.cc \
@ -750,13 +749,11 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/security/security_connector/ssl_utils.cc \
src/core/lib/security/security_connector/tls/tls_security_connector.cc \
src/core/lib/security/transport/client_auth_filter.cc \
src/core/lib/security/transport/legacy_server_auth_filter.cc \
src/core/lib/security/transport/secure_endpoint.cc \
src/core/lib/security/transport/security_handshaker.cc \
src/core/lib/security/transport/server_auth_filter.cc \
src/core/lib/security/transport/tsi_error.cc \
src/core/lib/security/util/json_util.cc \
src/core/lib/slice/b64.cc \
src/core/lib/slice/percent_encoding.cc \
src/core/lib/slice/slice.cc \
src/core/lib/slice/slice_buffer.cc \

3
config.w32 generated

@ -36,7 +36,6 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\filters\\http\\client_authority_filter.cc " +
"src\\core\\ext\\filters\\http\\http_filters_plugin.cc " +
"src\\core\\ext\\filters\\http\\message_compress\\compression_filter.cc " +
"src\\core\\ext\\filters\\http\\message_compress\\legacy_compression_filter.cc " +
"src\\core\\ext\\filters\\http\\server\\http_server_filter.cc " +
"src\\core\\ext\\filters\\message_size\\message_size_filter.cc " +
"src\\core\\ext\\filters\\rbac\\rbac_filter.cc " +
@ -715,13 +714,11 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\security\\security_connector\\ssl_utils.cc " +
"src\\core\\lib\\security\\security_connector\\tls\\tls_security_connector.cc " +
"src\\core\\lib\\security\\transport\\client_auth_filter.cc " +
"src\\core\\lib\\security\\transport\\legacy_server_auth_filter.cc " +
"src\\core\\lib\\security\\transport\\secure_endpoint.cc " +
"src\\core\\lib\\security\\transport\\security_handshaker.cc " +
"src\\core\\lib\\security\\transport\\server_auth_filter.cc " +
"src\\core\\lib\\security\\transport\\tsi_error.cc " +
"src\\core\\lib\\security\\util\\json_util.cc " +
"src\\core\\lib\\slice\\b64.cc " +
"src\\core\\lib\\slice\\percent_encoding.cc " +
"src\\core\\lib\\slice\\slice.cc " +
"src\\core\\lib\\slice\\slice_buffer.cc " +

@ -64,14 +64,18 @@ Support for [xDS v2 APIs](https://www.envoyproxy.io/docs/envoy/latest/api/api_su
[Fault Injection](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/fault/v3/fault.proto):<br> Only the following fields are supported:<ul><li>delay</li><li>abort</li><li>max_active_faults</li><li>headers</li></ul> | [A33](https://github.com/grpc/proposal/blob/master/A33-Fault-Injection.md) | v1.37.1 | v1.37.1 | v1.37.0 | v1.4.0 |
[Client Status Discovery Service](https://github.com/envoyproxy/envoy/blob/main/api/envoy/service/status/v3/csds.proto) | [A40](https://github.com/grpc/proposal/blob/master/A40-csds-support.md) | v1.37.1 (C++)<br>v1.38.0 (Python) | v1.37.1 | v1.37.0 | v1.5.0 |
[Aggregate Clusters](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/aggregate_cluster.html) and [Logical DNS Clusters](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/service_discovery.html#logical-dns) | [A37](https://github.com/grpc/proposal/blob/master/A37-xds-aggregate-and-logical-dns-clusters.md) | v1.47.0 | v1.39.0 | v1.52.2 | v1.9.0 |
[Ring hash](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/load_balancers#ring-hash) load balancing policy:<br> Only the following [policy specifiers](https://github.com/envoyproxy/envoy/blob/2443032526cf6e50d63d35770df9473dd0460fc0/api/envoy/config/route/v3/route_components.proto#L706) are supported:<ul><li>header</li><li>filter_state with key `io.grpc.channel_id`</li></ul>Only [`XX_HASH`](https://github.com/envoyproxy/envoy/blob/2443032526cf6e50d63d35770df9473dd0460fc0/api/envoy/config/cluster/v3/cluster.proto#L383) function is supported. | [A42](https://github.com/grpc/proposal/blob/master/A42-xds-ring-hash-lb-policy.md) | v1.40.0<br>(C++ and Python) | v1.40.1 | 1.41.0 | |
Aggregate Cluster Behavior Fixes | [A75](https://github.com/grpc/proposal/blob/master/A75-xds-aggregate-cluster-behavior-fixes.md) | v1.61.0 | | | |
[Ring hash](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/load_balancers#ring-hash) load balancing policy:<br> Only the following [policy specifiers](https://github.com/envoyproxy/envoy/blob/2443032526cf6e50d63d35770df9473dd0460fc0/api/envoy/config/route/v3/route_components.proto#L706) are supported:<ul><li>header</li><li>filter_state with key `io.grpc.channel_id`</li></ul>Only [`XX_HASH`](https://github.com/envoyproxy/envoy/blob/2443032526cf6e50d63d35770df9473dd0460fc0/api/envoy/config/cluster/v3/cluster.proto#L383) function is supported. | [A42](https://github.com/grpc/proposal/blob/master/A42-xds-ring-hash-lb-policy.md) | v1.40.0<br>(C++ and Python) | v1.40.1 | 1.41.0 | v1.10.0 |
[Retry](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#envoy-v3-api-msg-config-route-v3-retrypolicy):<br>Only the following fields are supported:<ul><li>retry_on for the following conditions: cancelled, deadline-exceeded, internal, resource-exhausted, and unavailable.</li><li>num_retries</li><li>retry_back_off</li></ul> | [A44](https://github.com/grpc/proposal/blob/master/A44-xds-retry.md) | v1.40.0<br>(C++ and Python) | v1.40.1 | 1.41.0 | v1.8.0 |
[Security](https://www.envoyproxy.io/docs/envoy/latest/configuration/security/security):<br>Uses [certificate providers](https://github.com/grpc/proposal/blob/master/A29-xds-tls-security.md#certificate-provider-plugin-framework) instead of SDS | [A29](https://github.com/grpc/proposal/blob/master/A29-xds-tls-security.md) | v1.41.0<br>(C++ and Python) | v1.41.0 | 1.41.0 | |
[Authorization (RBAC)](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/rbac/v3/rbac.proto):<br><ul><li>`LOG` action has no effect<li>CEL unsupported and rejected</ul> | [A41](https://github.com/grpc/proposal/blob/master/A41-xds-rbac.md) | v1.51.0<br>(C++ and Python) | v1.42.0 | 1.42.0 | |
[Least Request LB Policy](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/load_balancers.html#weighted-least-request) | [A48](https://github.com/grpc/proposal/blob/master/A48-xds-least-request-lb-policy.md) | | v1.48.0 | | |
[Outlier Detection](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/outlier):<br>Only the following detection types are supported:<ul><li>Success Rate</li><li>Failure Percentage</li></ul> | [A50](https://github.com/grpc/proposal/blob/master/A50-xds-outlier-detection.md) | v1.51.0 | v1.49.0 | v1.50.0 | v1.7.0 |
[Custom Load Balancer Configuration](https://github.com/envoyproxy/envoy/blob/57be3189ffa3372b34e9480d1f02b2d165e49077/api/envoy/config/cluster/v3/cluster.proto#L1208) | [A52](https://github.com/grpc/proposal/blob/master/A52-xds-custom-lb-policies.md) | v1.55.0 | v1.47.0 | v1.56.0 | |
[Custom Load Balancer Configuration](https://github.com/envoyproxy/envoy/blob/57be3189ffa3372b34e9480d1f02b2d165e49077/api/envoy/config/cluster/v3/cluster.proto#L1208) | [A52](https://github.com/grpc/proposal/blob/master/A52-xds-custom-lb-policies.md) | v1.55.0 | v1.47.0 | v1.56.0 | v1.10.0 |
[xDS Federation](https://github.com/cncf/xds/blob/main/proposals/TP1-xds-transport-next.md) | [A47](https://github.com/grpc/proposal/blob/master/A47-xds-federation.md) | v1.55.0 | v1.55.0 | v1.55.0 | |
[Client-Side Weighted Round Robin LB Policy](https://github.com/envoyproxy/envoy/blob/a6d46b6ac4750720eec9a49abe701f0df9bf8e0a/api/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3/client_side_weighted_round_robin.proto#L36) | [A58](https://github.com/grpc/proposal/blob/master/A58-client-side-weighted-round-robin-lb-policy.md) | v1.55.0 | v1.54.0 | v1.56.0 | |
Pick First | [A62](https://github.com/grpc/proposal/blob/master/A62-pick-first.md) | v1.58.0 | v1.58.1 | v1.56.0 | |
[StringMatcher for Header Matching](https://github.com/envoyproxy/envoy/blob/3fe4b8d335fa339ef6f17325c8d31f87ade7bb1a/api/envoy/config/route/v3/route_components.proto#L2280) | [A63](https://github.com/grpc/proposal/blob/master/A63-xds-string-matcher-in-header-matching.md) | v1.56.0 | v1.53.0 | v1.56.0 | v1.9.0 |
mTLS Credentials in xDS Bootstrap File | [A65](https://github.com/grpc/proposal/blob/master/A65-xds-mtls-creds-in-bootstrap.md) | v1.57.0 | | | |
LRS Custom Metrics Support | [A64](https://github.com/grpc/proposal/blob/master/A64-lrs-custom-metrics.md) | v1.54.0 | | | |
mTLS Credentials in xDS Bootstrap File | [A65](https://github.com/grpc/proposal/blob/master/A65-xds-mtls-creds-in-bootstrap.md) | v1.57.0 | | v1.61.0 | |
Stateful Session Affinity | [A55](https://github.com/grpc/proposal/blob/master/A55-xds-stateful-session-affinity.md), [A60](https://github.com/grpc/proposal/blob/master/A60-xds-stateful-session-affinity-weighted-clusters.md), [A75](https://github.com/grpc/proposal/blob/master/A75-xds-aggregate-cluster-behavior-fixes.md) | v1.61.0 | | | |

8
gRPC-C++.podspec generated

@ -291,7 +291,6 @@ Pod::Spec.new do |s|
'src/core/ext/filters/http/client/http_client_filter.h',
'src/core/ext/filters/http/client_authority_filter.h',
'src/core/ext/filters/http/message_compress/compression_filter.h',
'src/core/ext/filters/http/message_compress/legacy_compression_filter.h',
'src/core/ext/filters/http/server/http_server_filter.h',
'src/core/ext/filters/message_size/message_size_filter.h',
'src/core/ext/filters/rbac/rbac_filter.h',
@ -909,6 +908,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',
@ -930,6 +930,7 @@ Pod::Spec.new do |s|
'src/core/lib/event_engine/common_closures.h',
'src/core/lib/event_engine/default_event_engine.h',
'src/core/lib/event_engine/default_event_engine_factory.h',
'src/core/lib/event_engine/event_engine_context.h',
'src/core/lib/event_engine/extensions/can_track_errors.h',
'src/core/lib/event_engine/extensions/chaotic_good_extension.h',
'src/core/lib/event_engine/extensions/supports_fd.h',
@ -1215,7 +1216,6 @@ Pod::Spec.new do |s|
'src/core/lib/security/transport/security_handshaker.h',
'src/core/lib/security/transport/tsi_error.h',
'src/core/lib/security/util/json_util.h',
'src/core/lib/slice/b64.h',
'src/core/lib/slice/percent_encoding.h',
'src/core/lib/slice/slice.h',
'src/core/lib/slice/slice_buffer.h',
@ -1574,7 +1574,6 @@ Pod::Spec.new do |s|
'src/core/ext/filters/http/client/http_client_filter.h',
'src/core/ext/filters/http/client_authority_filter.h',
'src/core/ext/filters/http/message_compress/compression_filter.h',
'src/core/ext/filters/http/message_compress/legacy_compression_filter.h',
'src/core/ext/filters/http/server/http_server_filter.h',
'src/core/ext/filters/message_size/message_size_filter.h',
'src/core/ext/filters/rbac/rbac_filter.h',
@ -2174,6 +2173,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',
@ -2195,6 +2195,7 @@ Pod::Spec.new do |s|
'src/core/lib/event_engine/common_closures.h',
'src/core/lib/event_engine/default_event_engine.h',
'src/core/lib/event_engine/default_event_engine_factory.h',
'src/core/lib/event_engine/event_engine_context.h',
'src/core/lib/event_engine/extensions/can_track_errors.h',
'src/core/lib/event_engine/extensions/chaotic_good_extension.h',
'src/core/lib/event_engine/extensions/supports_fd.h',
@ -2480,7 +2481,6 @@ Pod::Spec.new do |s|
'src/core/lib/security/transport/security_handshaker.h',
'src/core/lib/security/transport/tsi_error.h',
'src/core/lib/security/util/json_util.h',
'src/core/lib/slice/b64.h',
'src/core/lib/slice/percent_encoding.h',
'src/core/lib/slice/slice.h',
'src/core/lib/slice/slice_buffer.h',

11
gRPC-Core.podspec generated

@ -292,8 +292,6 @@ Pod::Spec.new do |s|
'src/core/ext/filters/http/http_filters_plugin.cc',
'src/core/ext/filters/http/message_compress/compression_filter.cc',
'src/core/ext/filters/http/message_compress/compression_filter.h',
'src/core/ext/filters/http/message_compress/legacy_compression_filter.cc',
'src/core/ext/filters/http/message_compress/legacy_compression_filter.h',
'src/core/ext/filters/http/server/http_server_filter.cc',
'src/core/ext/filters/http/server/http_server_filter.h',
'src/core/ext/filters/message_size/message_size_filter.cc',
@ -1276,6 +1274,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',
@ -1318,6 +1317,7 @@ Pod::Spec.new do |s|
'src/core/lib/event_engine/default_event_engine_factory.cc',
'src/core/lib/event_engine/default_event_engine_factory.h',
'src/core/lib/event_engine/event_engine.cc',
'src/core/lib/event_engine/event_engine_context.h',
'src/core/lib/event_engine/extensions/can_track_errors.h',
'src/core/lib/event_engine/extensions/chaotic_good_extension.h',
'src/core/lib/event_engine/extensions/supports_fd.h',
@ -1852,7 +1852,6 @@ Pod::Spec.new do |s|
'src/core/lib/security/security_connector/tls/tls_security_connector.h',
'src/core/lib/security/transport/auth_filters.h',
'src/core/lib/security/transport/client_auth_filter.cc',
'src/core/lib/security/transport/legacy_server_auth_filter.cc',
'src/core/lib/security/transport/secure_endpoint.cc',
'src/core/lib/security/transport/secure_endpoint.h',
'src/core/lib/security/transport/security_handshaker.cc',
@ -1862,8 +1861,6 @@ Pod::Spec.new do |s|
'src/core/lib/security/transport/tsi_error.h',
'src/core/lib/security/util/json_util.cc',
'src/core/lib/security/util/json_util.h',
'src/core/lib/slice/b64.cc',
'src/core/lib/slice/b64.h',
'src/core/lib/slice/percent_encoding.cc',
'src/core/lib/slice/percent_encoding.h',
'src/core/lib/slice/slice.cc',
@ -2377,7 +2374,6 @@ Pod::Spec.new do |s|
'src/core/ext/filters/http/client/http_client_filter.h',
'src/core/ext/filters/http/client_authority_filter.h',
'src/core/ext/filters/http/message_compress/compression_filter.h',
'src/core/ext/filters/http/message_compress/legacy_compression_filter.h',
'src/core/ext/filters/http/server/http_server_filter.h',
'src/core/ext/filters/message_size/message_size_filter.h',
'src/core/ext/filters/rbac/rbac_filter.h',
@ -2956,6 +2952,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',
@ -2977,6 +2974,7 @@ Pod::Spec.new do |s|
'src/core/lib/event_engine/common_closures.h',
'src/core/lib/event_engine/default_event_engine.h',
'src/core/lib/event_engine/default_event_engine_factory.h',
'src/core/lib/event_engine/event_engine_context.h',
'src/core/lib/event_engine/extensions/can_track_errors.h',
'src/core/lib/event_engine/extensions/chaotic_good_extension.h',
'src/core/lib/event_engine/extensions/supports_fd.h',
@ -3262,7 +3260,6 @@ Pod::Spec.new do |s|
'src/core/lib/security/transport/security_handshaker.h',
'src/core/lib/security/transport/tsi_error.h',
'src/core/lib/security/util/json_util.h',
'src/core/lib/slice/b64.h',
'src/core/lib/slice/percent_encoding.h',
'src/core/lib/slice/slice.h',
'src/core/lib/slice/slice_buffer.h',

7
grpc.gemspec generated

@ -182,8 +182,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/filters/http/http_filters_plugin.cc )
s.files += %w( src/core/ext/filters/http/message_compress/compression_filter.cc )
s.files += %w( src/core/ext/filters/http/message_compress/compression_filter.h )
s.files += %w( src/core/ext/filters/http/message_compress/legacy_compression_filter.cc )
s.files += %w( src/core/ext/filters/http/message_compress/legacy_compression_filter.h )
s.files += %w( src/core/ext/filters/http/server/http_server_filter.cc )
s.files += %w( src/core/ext/filters/http/server/http_server_filter.h )
s.files += %w( src/core/ext/filters/message_size/message_size_filter.cc )
@ -1166,6 +1164,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 )
@ -1208,6 +1207,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/event_engine/default_event_engine_factory.cc )
s.files += %w( src/core/lib/event_engine/default_event_engine_factory.h )
s.files += %w( src/core/lib/event_engine/event_engine.cc )
s.files += %w( src/core/lib/event_engine/event_engine_context.h )
s.files += %w( src/core/lib/event_engine/extensions/can_track_errors.h )
s.files += %w( src/core/lib/event_engine/extensions/chaotic_good_extension.h )
s.files += %w( src/core/lib/event_engine/extensions/supports_fd.h )
@ -1742,7 +1742,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/security/security_connector/tls/tls_security_connector.h )
s.files += %w( src/core/lib/security/transport/auth_filters.h )
s.files += %w( src/core/lib/security/transport/client_auth_filter.cc )
s.files += %w( src/core/lib/security/transport/legacy_server_auth_filter.cc )
s.files += %w( src/core/lib/security/transport/secure_endpoint.cc )
s.files += %w( src/core/lib/security/transport/secure_endpoint.h )
s.files += %w( src/core/lib/security/transport/security_handshaker.cc )
@ -1752,8 +1751,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/security/transport/tsi_error.h )
s.files += %w( src/core/lib/security/util/json_util.cc )
s.files += %w( src/core/lib/security/util/json_util.h )
s.files += %w( src/core/lib/slice/b64.cc )
s.files += %w( src/core/lib/slice/b64.h )
s.files += %w( src/core/lib/slice/percent_encoding.cc )
s.files += %w( src/core/lib/slice/percent_encoding.h )
s.files += %w( src/core/lib/slice/slice.cc )

@ -100,12 +100,22 @@ class OpenTelemetryPluginBuilder {
OpenTelemetryPluginBuilder& SetGenericMethodAttributeFilter(
absl::AnyInvocable<bool(absl::string_view /*generic_method*/) const>
generic_method_attribute_filter);
// Methods to manipulate which instruments are enabled in the OpenTelemetry
// Stats Plugin.
OpenTelemetryPluginBuilder& EnableMetrics(
absl::Span<const absl::string_view> metric_names);
OpenTelemetryPluginBuilder& DisableMetrics(
absl::Span<const absl::string_view> metric_names);
OpenTelemetryPluginBuilder& DisableAllMetrics();
/// Add a plugin option to add to the opentelemetry plugin being built. At
/// present, this type is an opaque type. Ownership of \a option is
/// transferred when `AddPluginOption` is invoked. A maximum of 64 plugin
/// 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();

@ -19,6 +19,7 @@
#define GRPCPP_IMPL_SERVER_CALLBACK_HANDLERS_H
#include <grpc/grpc.h>
#include <grpc/impl/call.h>
#include <grpc/support/log.h>
#include <grpcpp/impl/rpc_service_method.h>
#include <grpcpp/server_context.h>
@ -186,6 +187,8 @@ class CallbackUnaryHandler : public grpc::internal::MethodHandler {
ctx_->set_message_allocator_state(allocator_state);
}
grpc_call* call() override { return call_.call(); }
/// SetupReactor binds the reactor (which also releases any queued
/// operations), maybe calls OnCancel if possible/needed, and maybe marks
/// the completion of the RPC. This should be the last component of the
@ -370,6 +373,8 @@ class CallbackClientStreamingHandler : public grpc::internal::MethodHandler {
std::function<void()> call_requester)
: ctx_(ctx), call_(*call), call_requester_(std::move(call_requester)) {}
grpc_call* call() override { return call_.call(); }
void SetupReactor(ServerReadReactor<RequestType>* reactor) {
reactor_.store(reactor, std::memory_order_relaxed);
// The callback for this function should not be inlined because it invokes
@ -595,6 +600,8 @@ class CallbackServerStreamingHandler : public grpc::internal::MethodHandler {
req_(req),
call_requester_(std::move(call_requester)) {}
grpc_call* call() override { return call_.call(); }
void SetupReactor(ServerWriteReactor<ResponseType>* reactor) {
reactor_.store(reactor, std::memory_order_relaxed);
// The callback for this function should not be inlined because it invokes
@ -807,6 +814,8 @@ class CallbackBidiHandler : public grpc::internal::MethodHandler {
std::function<void()> call_requester)
: ctx_(ctx), call_(*call), call_requester_(std::move(call_requester)) {}
grpc_call* call() override { return call_.call(); }
void SetupReactor(ServerBidiReactor<RequestType, ResponseType>* reactor) {
reactor_.store(reactor, std::memory_order_relaxed);
// The callbacks for these functions should not be inlined because they

@ -29,6 +29,7 @@
#include <vector>
#include <grpc/grpc.h>
#include <grpc/impl/call.h>
#include <grpc/impl/compression_types.h>
#include <grpcpp/impl/call.h>
#include <grpcpp/impl/call_op_set.h>
@ -520,7 +521,9 @@ class ServerContextBase {
public:
TestServerCallbackUnary(ServerContextBase* ctx,
std::function<void(grpc::Status)> func)
: reactor_(ctx->DefaultReactor()), func_(std::move(func)) {
: reactor_(ctx->DefaultReactor()),
func_(std::move(func)),
call_(ctx->c_call()) {
this->BindReactor(reactor_);
}
void Finish(grpc::Status s) override {
@ -537,12 +540,16 @@ class ServerContextBase {
private:
void CallOnDone() override {}
grpc_call* call() override { return call_; }
grpc::internal::ServerReactor* reactor() override { return reactor_; }
grpc::ServerUnaryReactor* const reactor_;
std::atomic_bool status_set_{false};
grpc::Status status_;
const std::function<void(grpc::Status s)> func_;
grpc_call* call_;
};
alignas(Reactor) char default_reactor_[sizeof(Reactor)];

@ -23,6 +23,9 @@
#include <functional>
#include <type_traits>
#include "absl/functional/any_invocable.h"
#include <grpc/impl/call.h>
#include <grpcpp/impl/call.h>
#include <grpcpp/impl/call_op_set.h>
#include <grpcpp/impl/sync.h>
@ -127,6 +130,12 @@ class ServerCallbackCall {
private:
virtual ServerReactor* reactor() = 0;
virtual grpc_call* call() = 0;
virtual void RunAsync(absl::AnyInvocable<void()> cb) {
grpc_call_run_in_event_engine(call(), std::move(cb));
}
// CallOnDone performs the work required at completion of the RPC: invoking
// the OnDone function and doing all necessary cleanup. This function is only
// ever invoked on a fully-Unref'fed ServerCallbackCall.

7
package.xml generated

@ -164,8 +164,6 @@
<file baseinstalldir="/" name="src/core/ext/filters/http/http_filters_plugin.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/http/message_compress/compression_filter.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/http/message_compress/compression_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/http/message_compress/legacy_compression_filter.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/http/message_compress/legacy_compression_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/http/server/http_server_filter.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/http/server/http_server_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/message_size/message_size_filter.cc" role="src" />
@ -1148,6 +1146,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" />
@ -1190,6 +1189,7 @@
<file baseinstalldir="/" name="src/core/lib/event_engine/default_event_engine_factory.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/event_engine/default_event_engine_factory.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/event_engine/event_engine.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/event_engine/event_engine_context.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/event_engine/extensions/can_track_errors.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/event_engine/extensions/chaotic_good_extension.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/event_engine/extensions/supports_fd.h" role="src" />
@ -1724,7 +1724,6 @@
<file baseinstalldir="/" name="src/core/lib/security/security_connector/tls/tls_security_connector.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/auth_filters.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/client_auth_filter.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/legacy_server_auth_filter.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/secure_endpoint.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/secure_endpoint.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/transport/security_handshaker.cc" role="src" />
@ -1734,8 +1733,6 @@
<file baseinstalldir="/" name="src/core/lib/security/transport/tsi_error.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/util/json_util.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/security/util/json_util.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/b64.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/b64.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/percent_encoding.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/percent_encoding.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/slice/slice.cc" role="src" />

@ -68,6 +68,7 @@ grpc_cc_library(
"absl/strings",
],
deps = [
":memory_quota",
"//:event_engine_base_hdrs",
"//:gpr_platform",
],
@ -119,6 +120,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",
@ -592,7 +596,7 @@ grpc_cc_library(
deps = [
"activity",
"context",
"default_event_engine",
"event_engine_context",
"poll",
"time",
"//:event_engine_base_hdrs",
@ -906,6 +910,7 @@ grpc_cc_library(
"atomic_utils",
"construct_destruct",
"context",
"event_engine_context",
"no_destruct",
"poll",
"promise_factory",
@ -2608,6 +2613,21 @@ grpc_cc_library(
],
)
grpc_cc_library(
name = "event_engine_context",
hdrs = [
"lib/event_engine/event_engine_context.h",
],
visibility = [
"@grpc:alt_grpc_base_legacy",
],
deps = [
"context",
"//:event_engine_base_hdrs",
"//:gpr",
],
)
grpc_cc_library(
name = "default_event_engine",
srcs = [
@ -2622,7 +2642,6 @@ grpc_cc_library(
],
deps = [
"channel_args",
"context",
"default_event_engine_factory",
"event_engine_trace",
"no_destruct",
@ -3549,6 +3568,7 @@ grpc_cc_library(
"channel_args",
"channel_fwd",
"context",
"event_engine_context",
"grpc_server_config_selector",
"grpc_service_config",
"metadata_batch",
@ -7008,6 +7028,8 @@ grpc_cc_library(
"activity",
"cancel_callback",
"event_engine_common",
"event_engine_extensions",
"event_engine_query_extensions",
"if",
"map",
"poll",
@ -7443,10 +7465,10 @@ grpc_cc_library(
"chaotic_good_settings_metadata",
"closure",
"context",
"default_event_engine",
"error",
"error_utils",
"event_engine_common",
"event_engine_context",
"event_engine_extensions",
"event_engine_query_extensions",
"event_engine_tcp_socket_utils",
@ -7532,6 +7554,7 @@ grpc_cc_library(
"//:api_trace",
"//:channel",
"//:channel_create",
"//:config",
"//:debug_location",
"//:exec_ctx",
"//:gpr",
@ -7563,10 +7586,14 @@ grpc_cc_library(
],
language = "c++",
deps = [
"arena",
"channel_args",
"no_destruct",
"slice",
"time",
"//:call_tracer",
"//:gpr",
"//:legacy_context",
],
)

@ -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,
@ -2894,6 +2895,15 @@ ClientChannelFilter::LoadBalancedCall::PickSubchannel(bool was_queued) {
set_picker(chand_->picker_);
}
while (true) {
// TODO(roth): Fix race condition in channel_idle filter and any
// other possible causes of this.
if (pickers.back() == nullptr) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
gpr_log(GPR_ERROR, "chand=%p lb_call=%p: picker is null, failing call",
chand_, this);
}
return absl::InternalError("picker is null -- shouldn't happen");
}
// Do pick.
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_lb_call_trace)) {
gpr_log(GPR_INFO, "chand=%p lb_call=%p: performing pick with picker=%p",

@ -46,13 +46,11 @@
#include "src/core/lib/address_utils/parse_address.h"
#include "src/core/lib/address_utils/sockaddr_utils.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/experiments/experiments.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/env.h"
#include "src/core/lib/gprpp/host_port.h"
#include "src/core/lib/gprpp/memory.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/slice/b64.h"
#include "src/core/lib/transport/http_connect_handshaker.h"
#include "src/core/lib/uri/uri_parser.h"
@ -260,14 +258,7 @@ absl::optional<std::string> HttpProxyMapper::MapName(
MaybeAddDefaultPort(absl::StripPrefix(uri->path(), "/")));
if (user_cred.has_value()) {
// Use base64 encoding for user credentials as stated in RFC 7617
std::string encoded_user_cred;
if (IsAbslBase64Enabled()) {
encoded_user_cred = absl::Base64Escape(*user_cred);
} else {
UniquePtr<char> tmp(
grpc_base64_encode(user_cred->data(), user_cred->length(), 0, 0));
encoded_user_cred = tmp.get();
}
std::string encoded_user_cred = absl::Base64Escape(*user_cred);
*args = args->Set(
GRPC_ARG_HTTP_CONNECT_HEADERS,
absl::StrCat("Proxy-Authorization:Basic ", encoded_user_cred));

@ -22,7 +22,6 @@
#include "src/core/ext/filters/http/client/http_client_filter.h"
#include "src/core/ext/filters/http/message_compress/compression_filter.h"
#include "src/core/ext/filters/http/message_compress/legacy_compression_filter.h"
#include "src/core/ext/filters/http/server/http_server_filter.h"
#include "src/core/ext/filters/message_size/message_size_filter.h"
#include "src/core/lib/channel/channel_args.h"
@ -40,40 +39,21 @@ bool IsBuildingHttpLikeTransport(const ChannelArgs& args) {
} // namespace
void RegisterHttpFilters(CoreConfiguration::Builder* builder) {
if (IsV3CompressionFilterEnabled()) {
builder->channel_init()
->RegisterFilter<ClientCompressionFilter>(GRPC_CLIENT_SUBCHANNEL)
.If(IsBuildingHttpLikeTransport)
.After<HttpClientFilter>()
.After<ClientMessageSizeFilter>();
builder->channel_init()
->RegisterFilter<ClientCompressionFilter>(GRPC_CLIENT_DIRECT_CHANNEL)
.If(IsBuildingHttpLikeTransport)
.After<HttpClientFilter>()
.After<ClientMessageSizeFilter>();
builder->channel_init()
->RegisterFilter<ServerCompressionFilter>(GRPC_SERVER_CHANNEL)
.If(IsBuildingHttpLikeTransport)
.After<HttpServerFilter>()
.After<ServerMessageSizeFilter>();
} else {
builder->channel_init()
->RegisterFilter<LegacyClientCompressionFilter>(GRPC_CLIENT_SUBCHANNEL)
.If(IsBuildingHttpLikeTransport)
.After<HttpClientFilter>()
.After<ClientMessageSizeFilter>();
builder->channel_init()
->RegisterFilter<LegacyClientCompressionFilter>(
GRPC_CLIENT_DIRECT_CHANNEL)
.If(IsBuildingHttpLikeTransport)
.After<HttpClientFilter>()
.After<ClientMessageSizeFilter>();
builder->channel_init()
->RegisterFilter<LegacyServerCompressionFilter>(GRPC_SERVER_CHANNEL)
.If(IsBuildingHttpLikeTransport)
.After<HttpServerFilter>()
.After<ServerMessageSizeFilter>();
}
builder->channel_init()
->RegisterFilter<ClientCompressionFilter>(GRPC_CLIENT_SUBCHANNEL)
.If(IsBuildingHttpLikeTransport)
.After<HttpClientFilter>()
.After<ClientMessageSizeFilter>();
builder->channel_init()
->RegisterFilter<ClientCompressionFilter>(GRPC_CLIENT_DIRECT_CHANNEL)
.If(IsBuildingHttpLikeTransport)
.After<HttpClientFilter>()
.After<ClientMessageSizeFilter>();
builder->channel_init()
->RegisterFilter<ServerCompressionFilter>(GRPC_SERVER_CHANNEL)
.If(IsBuildingHttpLikeTransport)
.After<HttpServerFilter>()
.After<ServerMessageSizeFilter>();
builder->channel_init()
->RegisterFilter<HttpClientFilter>(GRPC_CLIENT_SUBCHANNEL)
.If(IsBuildingHttpLikeTransport)

@ -1,328 +0,0 @@
// Copyright 2022 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/core/ext/filters/http/message_compress/legacy_compression_filter.h"
#include <inttypes.h>
#include <functional>
#include <memory>
#include <utility>
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/types/optional.h"
#include <grpc/compression.h>
#include <grpc/grpc.h>
#include <grpc/impl/channel_arg_names.h>
#include <grpc/impl/compression_types.h>
#include <grpc/support/log.h>
#include "src/core/ext/filters/message_size/message_size_filter.h"
#include "src/core/lib/channel/call_tracer.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/channel/context.h"
#include "src/core/lib/channel/promise_based_filter.h"
#include "src/core/lib/compression/compression_internal.h"
#include "src/core/lib/compression/message_compress.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/promise/activity.h"
#include "src/core/lib/promise/context.h"
#include "src/core/lib/promise/latch.h"
#include "src/core/lib/promise/pipe.h"
#include "src/core/lib/promise/prioritized_race.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/slice/slice_buffer.h"
#include "src/core/lib/surface/call.h"
#include "src/core/lib/surface/call_trace.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/transport.h"
namespace grpc_core {
const grpc_channel_filter LegacyClientCompressionFilter::kFilter =
MakePromiseBasedFilter<
LegacyClientCompressionFilter, FilterEndpoint::kClient,
kFilterExaminesServerInitialMetadata | kFilterExaminesInboundMessages |
kFilterExaminesOutboundMessages>("compression");
const grpc_channel_filter LegacyServerCompressionFilter::kFilter =
MakePromiseBasedFilter<
LegacyServerCompressionFilter, FilterEndpoint::kServer,
kFilterExaminesServerInitialMetadata | kFilterExaminesInboundMessages |
kFilterExaminesOutboundMessages>("compression");
absl::StatusOr<LegacyClientCompressionFilter>
LegacyClientCompressionFilter::Create(const ChannelArgs& args,
ChannelFilter::Args) {
return LegacyClientCompressionFilter(args);
}
absl::StatusOr<LegacyServerCompressionFilter>
LegacyServerCompressionFilter::Create(const ChannelArgs& args,
ChannelFilter::Args) {
return LegacyServerCompressionFilter(args);
}
LegacyCompressionFilter::LegacyCompressionFilter(const ChannelArgs& args)
: max_recv_size_(GetMaxRecvSizeFromChannelArgs(args)),
message_size_service_config_parser_index_(
MessageSizeParser::ParserIndex()),
default_compression_algorithm_(
DefaultCompressionAlgorithmFromChannelArgs(args).value_or(
GRPC_COMPRESS_NONE)),
enabled_compression_algorithms_(
CompressionAlgorithmSet::FromChannelArgs(args)),
enable_compression_(
args.GetBool(GRPC_ARG_ENABLE_PER_MESSAGE_COMPRESSION).value_or(true)),
enable_decompression_(
args.GetBool(GRPC_ARG_ENABLE_PER_MESSAGE_DECOMPRESSION)
.value_or(true)) {
// Make sure the default is enabled.
if (!enabled_compression_algorithms_.IsSet(default_compression_algorithm_)) {
const char* name;
if (!grpc_compression_algorithm_name(default_compression_algorithm_,
&name)) {
name = "<unknown>";
}
gpr_log(GPR_ERROR,
"default compression algorithm %s not enabled: switching to none",
name);
default_compression_algorithm_ = GRPC_COMPRESS_NONE;
}
}
MessageHandle LegacyCompressionFilter::CompressMessage(
MessageHandle message, grpc_compression_algorithm algorithm) const {
if (GRPC_TRACE_FLAG_ENABLED(grpc_compression_trace)) {
gpr_log(GPR_INFO, "CompressMessage: len=%" PRIdPTR " alg=%d flags=%d",
message->payload()->Length(), algorithm, message->flags());
}
auto* call_context = GetContext<grpc_call_context_element>();
auto* call_tracer = static_cast<CallTracerInterface*>(
call_context[GRPC_CONTEXT_CALL_TRACER].value);
if (call_tracer != nullptr) {
call_tracer->RecordSendMessage(*message->payload());
}
// Check if we're allowed to compress this message
// (apps might want to disable compression for certain messages to avoid
// crime/beast like vulns).
uint32_t& flags = message->mutable_flags();
if (algorithm == GRPC_COMPRESS_NONE || !enable_compression_ ||
(flags & (GRPC_WRITE_NO_COMPRESS | GRPC_WRITE_INTERNAL_COMPRESS))) {
return message;
}
// Try to compress the payload.
SliceBuffer tmp;
SliceBuffer* payload = message->payload();
bool did_compress = grpc_msg_compress(algorithm, payload->c_slice_buffer(),
tmp.c_slice_buffer());
// If we achieved compression send it as compressed, otherwise send it as (to
// avoid spending cycles on the receiver decompressing).
if (did_compress) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_compression_trace)) {
const char* algo_name;
const size_t before_size = payload->Length();
const size_t after_size = tmp.Length();
const float savings_ratio = 1.0f - static_cast<float>(after_size) /
static_cast<float>(before_size);
GPR_ASSERT(grpc_compression_algorithm_name(algorithm, &algo_name));
gpr_log(GPR_INFO,
"Compressed[%s] %" PRIuPTR " bytes vs. %" PRIuPTR
" bytes (%.2f%% savings)",
algo_name, before_size, after_size, 100 * savings_ratio);
}
tmp.Swap(payload);
flags |= GRPC_WRITE_INTERNAL_COMPRESS;
if (call_tracer != nullptr) {
call_tracer->RecordSendCompressedMessage(*message->payload());
}
} else {
if (GRPC_TRACE_FLAG_ENABLED(grpc_compression_trace)) {
const char* algo_name;
GPR_ASSERT(grpc_compression_algorithm_name(algorithm, &algo_name));
gpr_log(GPR_INFO,
"Algorithm '%s' enabled but decided not to compress. Input size: "
"%" PRIuPTR,
algo_name, payload->Length());
}
}
return message;
}
absl::StatusOr<MessageHandle> LegacyCompressionFilter::DecompressMessage(
bool is_client, MessageHandle message, DecompressArgs args) const {
if (GRPC_TRACE_FLAG_ENABLED(grpc_compression_trace)) {
gpr_log(GPR_INFO, "DecompressMessage: len=%" PRIdPTR " max=%d alg=%d",
message->payload()->Length(),
args.max_recv_message_length.value_or(-1), args.algorithm);
}
auto* call_context = GetContext<grpc_call_context_element>();
auto* call_tracer = static_cast<CallTracerInterface*>(
call_context[GRPC_CONTEXT_CALL_TRACER].value);
if (call_tracer != nullptr) {
call_tracer->RecordReceivedMessage(*message->payload());
}
// Check max message length.
if (args.max_recv_message_length.has_value() &&
message->payload()->Length() >
static_cast<size_t>(*args.max_recv_message_length)) {
return absl::ResourceExhaustedError(absl::StrFormat(
"%s: Received message larger than max (%u vs. %d)",
is_client ? "CLIENT" : "SERVER", message->payload()->Length(),
*args.max_recv_message_length));
}
// Check if decompression is enabled (if not, we can just pass the message
// up).
if (!enable_decompression_ ||
(message->flags() & GRPC_WRITE_INTERNAL_COMPRESS) == 0) {
return std::move(message);
}
// Try to decompress the payload.
SliceBuffer decompressed_slices;
if (grpc_msg_decompress(args.algorithm, message->payload()->c_slice_buffer(),
decompressed_slices.c_slice_buffer()) == 0) {
return absl::InternalError(
absl::StrCat("Unexpected error decompressing data for algorithm ",
CompressionAlgorithmAsString(args.algorithm)));
}
// Swap the decompressed slices into the message.
message->payload()->Swap(&decompressed_slices);
message->mutable_flags() &= ~GRPC_WRITE_INTERNAL_COMPRESS;
message->mutable_flags() |= GRPC_WRITE_INTERNAL_TEST_ONLY_WAS_COMPRESSED;
if (call_tracer != nullptr) {
call_tracer->RecordReceivedDecompressedMessage(*message->payload());
}
return std::move(message);
}
grpc_compression_algorithm LegacyCompressionFilter::HandleOutgoingMetadata(
grpc_metadata_batch& outgoing_metadata) {
const auto algorithm = outgoing_metadata.Take(GrpcInternalEncodingRequest())
.value_or(default_compression_algorithm());
// Convey supported compression algorithms.
outgoing_metadata.Set(GrpcAcceptEncodingMetadata(),
enabled_compression_algorithms());
if (algorithm != GRPC_COMPRESS_NONE) {
outgoing_metadata.Set(GrpcEncodingMetadata(), algorithm);
}
return algorithm;
}
LegacyCompressionFilter::DecompressArgs
LegacyCompressionFilter::HandleIncomingMetadata(
const grpc_metadata_batch& incoming_metadata) {
// Configure max receive size.
auto max_recv_message_length = max_recv_size_;
const MessageSizeParsedConfig* limits =
MessageSizeParsedConfig::GetFromCallContext(
GetContext<grpc_call_context_element>(),
message_size_service_config_parser_index_);
if (limits != nullptr && limits->max_recv_size().has_value() &&
(!max_recv_message_length.has_value() ||
*limits->max_recv_size() < *max_recv_message_length)) {
max_recv_message_length = *limits->max_recv_size();
}
return DecompressArgs{incoming_metadata.get(GrpcEncodingMetadata())
.value_or(GRPC_COMPRESS_NONE),
max_recv_message_length};
}
ArenaPromise<ServerMetadataHandle>
LegacyClientCompressionFilter::MakeCallPromise(
CallArgs call_args, NextPromiseFactory next_promise_factory) {
auto compression_algorithm =
HandleOutgoingMetadata(*call_args.client_initial_metadata);
call_args.client_to_server_messages->InterceptAndMap(
[compression_algorithm,
this](MessageHandle message) -> absl::optional<MessageHandle> {
return CompressMessage(std::move(message), compression_algorithm);
});
auto* decompress_args = GetContext<Arena>()->New<DecompressArgs>(
DecompressArgs{GRPC_COMPRESS_ALGORITHMS_COUNT, absl::nullopt});
auto* decompress_err =
GetContext<Arena>()->New<Latch<ServerMetadataHandle>>();
call_args.server_initial_metadata->InterceptAndMap(
[decompress_args, this](ServerMetadataHandle server_initial_metadata)
-> absl::optional<ServerMetadataHandle> {
if (server_initial_metadata == nullptr) return absl::nullopt;
*decompress_args = HandleIncomingMetadata(*server_initial_metadata);
return std::move(server_initial_metadata);
});
call_args.server_to_client_messages->InterceptAndMap(
[decompress_err, decompress_args,
this](MessageHandle message) -> absl::optional<MessageHandle> {
auto r = DecompressMessage(/*is_client=*/true, std::move(message),
*decompress_args);
if (!r.ok()) {
decompress_err->Set(ServerMetadataFromStatus(r.status()));
return absl::nullopt;
}
return std::move(*r);
});
// Run the next filter, and race it with getting an error from decompression.
return PrioritizedRace(decompress_err->Wait(),
next_promise_factory(std::move(call_args)));
}
ArenaPromise<ServerMetadataHandle>
LegacyServerCompressionFilter::MakeCallPromise(
CallArgs call_args, NextPromiseFactory next_promise_factory) {
auto decompress_args =
HandleIncomingMetadata(*call_args.client_initial_metadata);
auto* decompress_err =
GetContext<Arena>()->New<Latch<ServerMetadataHandle>>();
call_args.client_to_server_messages->InterceptAndMap(
[decompress_err, decompress_args,
this](MessageHandle message) -> absl::optional<MessageHandle> {
auto r = DecompressMessage(/*is_client=*/false, std::move(message),
decompress_args);
if (grpc_call_trace.enabled()) {
gpr_log(GPR_DEBUG, "%s[compression] DecompressMessage returned %s",
GetContext<Activity>()->DebugTag().c_str(),
r.status().ToString().c_str());
}
if (!r.ok()) {
decompress_err->Set(ServerMetadataFromStatus(r.status()));
return absl::nullopt;
}
return std::move(*r);
});
auto* compression_algorithm =
GetContext<Arena>()->New<grpc_compression_algorithm>();
call_args.server_initial_metadata->InterceptAndMap(
[this, compression_algorithm](ServerMetadataHandle md) {
if (grpc_call_trace.enabled()) {
gpr_log(GPR_INFO, "%s[compression] Write metadata",
GetContext<Activity>()->DebugTag().c_str());
}
// Find the compression algorithm.
*compression_algorithm = HandleOutgoingMetadata(*md);
return md;
});
call_args.server_to_client_messages->InterceptAndMap(
[compression_algorithm,
this](MessageHandle message) -> absl::optional<MessageHandle> {
return CompressMessage(std::move(message), *compression_algorithm);
});
// Run the next filter, and race it with getting an error from decompression.
return PrioritizedRace(decompress_err->Wait(),
next_promise_factory(std::move(call_args)));
}
} // namespace grpc_core

@ -1,140 +0,0 @@
//
//
// Copyright 2020 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_EXT_FILTERS_HTTP_MESSAGE_COMPRESS_LEGACY_COMPRESSION_FILTER_H
#define GRPC_SRC_CORE_EXT_FILTERS_HTTP_MESSAGE_COMPRESS_LEGACY_COMPRESSION_FILTER_H
#include <grpc/support/port_platform.h>
#include <stddef.h>
#include <stdint.h>
#include "absl/status/statusor.h"
#include "absl/types/optional.h"
#include <grpc/impl/compression_types.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/compression/compression_internal.h"
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/transport.h"
namespace grpc_core {
/// Compression filter for messages.
///
/// See <grpc/compression.h> for the available compression settings.
///
/// Compression settings may come from:
/// - Channel configuration, as established at channel creation time.
/// - The metadata accompanying the outgoing data to be compressed. This is
/// taken as a request only. We may choose not to honor it. The metadata key
/// is given by \a GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY.
///
/// Compression can be disabled for concrete messages (for instance in order to
/// prevent CRIME/BEAST type attacks) by having the GRPC_WRITE_NO_COMPRESS set
/// in the MessageHandle flags.
///
/// The attempted compression mechanism is added to the resulting initial
/// metadata under the 'grpc-encoding' key.
///
/// If compression is actually performed, the MessageHandle's flag is modified
/// to incorporate GRPC_WRITE_INTERNAL_COMPRESS. Otherwise, and regardless of
/// the aforementioned 'grpc-encoding' metadata value, data will pass through
/// uncompressed.
class LegacyCompressionFilter : public ChannelFilter {
protected:
struct DecompressArgs {
grpc_compression_algorithm algorithm;
absl::optional<uint32_t> max_recv_message_length;
};
explicit LegacyCompressionFilter(const ChannelArgs& args);
grpc_compression_algorithm default_compression_algorithm() const {
return default_compression_algorithm_;
}
CompressionAlgorithmSet enabled_compression_algorithms() const {
return enabled_compression_algorithms_;
}
grpc_compression_algorithm HandleOutgoingMetadata(
grpc_metadata_batch& outgoing_metadata);
DecompressArgs HandleIncomingMetadata(
const grpc_metadata_batch& incoming_metadata);
// Compress one message synchronously.
MessageHandle CompressMessage(MessageHandle message,
grpc_compression_algorithm algorithm) const;
// Decompress one message synchronously.
absl::StatusOr<MessageHandle> DecompressMessage(bool is_client,
MessageHandle message,
DecompressArgs args) const;
private:
// Max receive message length, if set.
absl::optional<uint32_t> max_recv_size_;
size_t message_size_service_config_parser_index_;
// The default, channel-level, compression algorithm.
grpc_compression_algorithm default_compression_algorithm_;
// Enabled compression algorithms.
CompressionAlgorithmSet enabled_compression_algorithms_;
// Is compression enabled?
bool enable_compression_;
// Is decompression enabled?
bool enable_decompression_;
};
class LegacyClientCompressionFilter final : public LegacyCompressionFilter {
public:
static const grpc_channel_filter kFilter;
static absl::StatusOr<LegacyClientCompressionFilter> Create(
const ChannelArgs& args, ChannelFilter::Args filter_args);
// Construct a promise for one call.
ArenaPromise<ServerMetadataHandle> MakeCallPromise(
CallArgs call_args, NextPromiseFactory next_promise_factory) override;
private:
using LegacyCompressionFilter::LegacyCompressionFilter;
};
class LegacyServerCompressionFilter final : public LegacyCompressionFilter {
public:
static const grpc_channel_filter kFilter;
static absl::StatusOr<LegacyServerCompressionFilter> Create(
const ChannelArgs& args, ChannelFilter::Args filter_args);
// Construct a promise for one call.
ArenaPromise<ServerMetadataHandle> MakeCallPromise(
CallArgs call_args, NextPromiseFactory next_promise_factory) override;
private:
using LegacyCompressionFilter::LegacyCompressionFilter;
};
} // namespace grpc_core
#endif // GRPC_SRC_CORE_EXT_FILTERS_HTTP_MESSAGE_COMPRESS_LEGACY_COMPRESSION_FILTER_H

@ -31,6 +31,7 @@
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/context.h"
#include "src/core/lib/channel/promise_based_filter.h"
#include "src/core/lib/event_engine/event_engine_context.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/gprpp/status_helper.h"
#include "src/core/lib/gprpp/sync.h"

@ -17,6 +17,9 @@
#include <grpc/support/port_platform.h>
#include <cstdint>
#include <utility>
#include "absl/random/random.h"
#include "src/core/ext/transport/chaotic_good/frame.h"
@ -43,7 +46,12 @@ class ChaoticGoodTransport : public RefCounted<ChaoticGoodTransport> {
: control_endpoint_(std::move(control_endpoint)),
data_endpoint_(std::move(data_endpoint)),
encoder_(std::move(hpack_encoder)),
parser_(std::move(hpack_parser)) {}
parser_(std::move(hpack_parser)) {
// Enable RxMemoryAlignment and RPC receive coalescing after the transport
// setup is complete. At this point all the settings frames should have
// been read.
data_endpoint_.EnforceRxMemoryAlignmentAndCoalescing();
}
auto WriteFrame(const FrameInterface& frame) {
auto buffers = frame.Serialize(&encoder_);
@ -82,25 +90,25 @@ class ChaoticGoodTransport : public RefCounted<ChaoticGoodTransport> {
return If(
frame_header.ok(),
[this, &frame_header] {
const uint32_t message_padding = std::exchange(
last_message_padding_, frame_header->message_padding);
const uint32_t message_padding = frame_header->message_padding;
const uint32_t message_length = frame_header->message_length;
return Map(
TryJoin<absl::StatusOr>(
control_endpoint_.Read(frame_header->GetFrameLength()),
TrySeq(data_endpoint_.Read(message_padding),
[this, message_length]() {
return data_endpoint_.Read(message_length);
})),
[frame_header = *frame_header](
data_endpoint_.Read(message_length + message_padding)),
[frame_header = *frame_header, message_padding](
absl::StatusOr<std::tuple<SliceBuffer, SliceBuffer>>
buffers)
-> absl::StatusOr<std::tuple<FrameHeader, BufferPair>> {
if (!buffers.ok()) return buffers.status();
SliceBuffer data_read = std::move(std::get<1>(*buffers));
if (message_padding > 0) {
data_read.RemoveLastNBytesNoInline(message_padding);
}
return std::tuple<FrameHeader, BufferPair>(
frame_header,
BufferPair{std::move(std::get<0>(*buffers)),
std::move(std::get<1>(*buffers))});
std::move(data_read)});
});
},
[&frame_header]() {
@ -127,7 +135,6 @@ class ChaoticGoodTransport : public RefCounted<ChaoticGoodTransport> {
private:
PromiseEndpoint control_endpoint_;
PromiseEndpoint data_endpoint_;
uint32_t last_message_padding_ = 0;
HPackCompressor encoder_;
HPackParser parser_;
absl::BitGen bitgen_;

@ -33,8 +33,8 @@
#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/default_event_engine.h"
#include "src/core/lib/event_engine/extensions/chaotic_good_extension.h"
#include "src/core/lib/event_engine/query_extensions.h"
#include "src/core/lib/event_engine/tcp_socket_utils.h"
@ -257,6 +257,8 @@ void ChaoticGoodConnector::Connect(const Args& args, Result* result,
endpoint.value().get());
if (chaotic_good_ext != nullptr) {
chaotic_good_ext->EnableStatsCollection(/*is_control_channel=*/true);
chaotic_good_ext->UseMemoryQuota(
ResourceQuota::Default()->memory_quota());
}
p->handshake_mgr_->DoHandshake(
grpc_event_engine_endpoint_create(std::move(endpoint.value())),

@ -38,7 +38,7 @@
#include "src/core/ext/transport/chaotic_good/settings_metadata.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/event_engine/channel_args_endpoint_config.h"
#include "src/core/lib/event_engine/default_event_engine.h"
#include "src/core/lib/event_engine/event_engine_context.h"
#include "src/core/lib/event_engine/extensions/chaotic_good_extension.h"
#include "src/core/lib/event_engine/query_extensions.h"
#include "src/core/lib/event_engine/resolved_address_internal.h"
@ -59,6 +59,7 @@
#include "src/core/lib/promise/sleep.h"
#include "src/core/lib/promise/try_seq.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/resource_quota/resource_quota.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/slice/slice_buffer.h"
#include "src/core/lib/surface/server.h"
@ -418,6 +419,11 @@ void ChaoticGoodServerListener::ActiveConnection::HandshakingState::
[self, chaotic_good_ext](bool is_control_endpoint) {
if (chaotic_good_ext != nullptr) {
chaotic_good_ext->EnableStatsCollection(is_control_endpoint);
if (is_control_endpoint) {
// Control endpoint should use the default memory quota
chaotic_good_ext->UseMemoryQuota(
ResourceQuota::Default()->memory_quota());
}
}
return EndpointWriteSettingsFrame(self, is_control_endpoint);
});

@ -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"

@ -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, "");

@ -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.

@ -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_;
@ -312,23 +363,31 @@ void GlobalStatsPluginRegistry::RegisterStatsPlugin(
}
GlobalStatsPluginRegistry::StatsPluginGroup
GlobalStatsPluginRegistry::GetAllStatsPlugins() {
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
const StatsPlugin::ChannelScope& scope) {
MutexLock lock(&*mutex_);
StatsPluginGroup group;
for (const auto& plugin : *plugins_) {
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::GetStatsPluginsForChannel(
const StatsPlugin::ChannelScope& scope) {
GlobalStatsPluginRegistry::GetStatsPluginsForServer(const ChannelArgs& args) {
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->IsEnabledForServer(args);
if (is_enabled) {
group.AddStatsPlugin(plugin, std::move(config));
}
}
return group;

@ -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);
}
}
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);
// 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::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;

@ -47,8 +47,8 @@
#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/event_engine/default_event_engine.h" // IWYU pragma: keep
#include "src/core/lib/gprpp/crash.h"
#include "src/core/lib/event_engine/default_event_engine.h"
#include "src/core/lib/event_engine/event_engine_context.h" // IWYU pragma: keep
#include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/gprpp/time.h"
#include "src/core/lib/iomgr/call_combiner.h"

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

@ -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

@ -23,12 +23,6 @@
#include "src/core/lib/config/core_configuration.h"
#include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/promise/context.h"
namespace grpc_core {
template <>
struct ContextType<grpc_event_engine::experimental::EventEngine> {};
} // namespace grpc_core
namespace grpc_event_engine {
namespace experimental {

@ -0,0 +1,31 @@
// Copyright 2024 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_EVENT_ENGINE_EVENT_ENGINE_CONTEXT_H
#define GRPC_SRC_CORE_LIB_EVENT_ENGINE_EVENT_ENGINE_CONTEXT_H
#include <grpc/support/port_platform.h>
#include <grpc/event_engine/event_engine.h>
#include "src/core/lib/promise/context.h"
namespace grpc_core {
template <>
struct ContextType<grpc_event_engine::experimental::EventEngine> {};
} // namespace grpc_core
#endif // GRPC_SRC_CORE_LIB_EVENT_ENGINE_EVENT_ENGINE_CONTEXT_H

@ -19,6 +19,8 @@
#include "absl/strings/string_view.h"
#include "src/core/lib/resource_quota/memory_quota.h"
namespace grpc_event_engine {
namespace experimental {
@ -37,6 +39,24 @@ class ChaoticGoodExtension {
/// Otherwise they are grouped into histograms and counters specific to the
/// chaotic good data channel.
virtual void EnableStatsCollection(bool is_control_channel) = 0;
/// Forces the endpoint to use the provided memory quota instead of using the
/// one provided to it through the channel args. It is safe to call this
/// only when there are no outstanding Reads on the Endpoint.
virtual void UseMemoryQuota(grpc_core::MemoryQuotaRefPtr mem_quota) = 0;
/// Forces the endpoint to receive rpcs in one contiguous block of memory.
/// It is safe to call this only when there are no outstanding Reads on
/// the Endpoint.
virtual void EnableRpcReceiveCoalescing() = 0;
/// Disables rpc receive coalescing until it is explicitly enabled again.
/// It is safe to call this only when there are no outstanding Reads on
/// the Endpoint.
virtual void DisableRpcReceiveCoalescing() = 0;
/// If invoked, the endpoint tries to preserve proper order and alignment of
/// any memory that maybe shared across reads.
virtual void EnforceRxMemoryAlignment() = 0;
};
} // namespace experimental

@ -25,7 +25,7 @@
#include <utility>
#include "absl/functional/any_invocable.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
@ -49,9 +49,16 @@ struct ForcedExperiment {
bool forced = false;
bool value;
};
ForcedExperiment g_forced_experiments[kNumExperiments];
std::atomic<bool> g_loaded(false);
ForcedExperiment* ForcedExperiments() {
static NoDestruct<ForcedExperiment> forced_experiments[kNumExperiments];
return &**forced_experiments;
}
std::atomic<bool>* Loaded() {
static NoDestruct<std::atomic<bool>> loaded(false);
return &*loaded;
}
absl::AnyInvocable<bool(struct ExperimentMetadata)>* g_check_constraints_cb =
nullptr;
@ -98,7 +105,7 @@ GPR_ATTRIBUTE_NOINLINE Experiments LoadExperimentsFromConfigVariableInner() {
// Set defaults from metadata.
Experiments experiments;
for (size_t i = 0; i < kNumExperiments; i++) {
if (!g_forced_experiments[i].forced) {
if (!ForcedExperiments()[i].forced) {
if (g_check_constraints_cb != nullptr) {
experiments.enabled[i] =
(*g_check_constraints_cb)(g_experiment_metadata[i]);
@ -106,7 +113,7 @@ GPR_ATTRIBUTE_NOINLINE Experiments LoadExperimentsFromConfigVariableInner() {
experiments.enabled[i] = g_experiment_metadata[i].default_value;
}
} else {
experiments.enabled[i] = g_forced_experiments[i].value;
experiments.enabled[i] = ForcedExperiments()[i].value;
}
}
// For each comma-separated experiment in the global config:
@ -151,7 +158,7 @@ GPR_ATTRIBUTE_NOINLINE Experiments LoadExperimentsFromConfigVariableInner() {
}
Experiments LoadExperimentsFromConfigVariable() {
g_loaded.store(true, std::memory_order_relaxed);
Loaded()->store(true, std::memory_order_relaxed);
return LoadExperimentsFromConfigVariableInner();
}
@ -187,54 +194,65 @@ bool IsTestExperimentEnabled(size_t experiment_id) {
}
void PrintExperimentsList() {
size_t max_experiment_length = 0;
// Populate visitation order into a std::map so that iteration results in a
// lexical ordering of experiment names.
// The lexical ordering makes it nice and easy to find the experiment you're
// looking for in the output spam that we generate.
std::map<absl::string_view, size_t> visitation_order;
std::map<std::string, std::string> experiment_status;
std::set<std::string> defaulted_on_experiments;
for (size_t i = 0; i < kNumExperiments; i++) {
max_experiment_length =
std::max(max_experiment_length, strlen(g_experiment_metadata[i].name));
visitation_order[g_experiment_metadata[i].name] = i;
const char* name = g_experiment_metadata[i].name;
const bool enabled = IsExperimentEnabled(i);
const bool default_enabled = g_experiment_metadata[i].default_value;
const bool forced = ForcedExperiments()[i].forced;
if (!default_enabled && !enabled) continue;
if (default_enabled && enabled) {
defaulted_on_experiments.insert(name);
continue;
}
if (enabled) {
if (g_check_constraints_cb != nullptr &&
(*g_check_constraints_cb)(g_experiment_metadata[i])) {
experiment_status[name] = "on:constraints";
continue;
}
if (forced && ForcedExperiments()[i].value) {
experiment_status[name] = "on:forced";
continue;
}
experiment_status[name] = "on";
} else {
if (forced && !ForcedExperiments()[i].value) {
experiment_status[name] = "off:forced";
continue;
}
experiment_status[name] = "off";
}
}
for (auto name_index : visitation_order) {
const size_t i = name_index.second;
gpr_log(
GPR_INFO, "%s",
absl::StrCat(
"gRPC EXPERIMENT ", g_experiment_metadata[i].name,
std::string(max_experiment_length -
strlen(g_experiment_metadata[i].name) + 1,
' '),
IsExperimentEnabled(i) ? "ON " : "OFF",
" (default:", g_experiment_metadata[i].default_value ? "ON" : "OFF",
(g_check_constraints_cb != nullptr
? absl::StrCat(
" + ", g_experiment_metadata[i].additional_constaints,
" => ",
(*g_check_constraints_cb)(g_experiment_metadata[i])
? "ON "
: "OFF")
: std::string()),
g_forced_experiments[i].forced
? absl::StrCat(" force:",
g_forced_experiments[i].value ? "ON" : "OFF")
: std::string(),
")")
.c_str());
if (experiment_status.empty()) {
if (!defaulted_on_experiments.empty()) {
gpr_log(GPR_INFO, "gRPC experiments enabled: %s",
absl::StrJoin(defaulted_on_experiments, ", ").c_str());
}
} else {
if (defaulted_on_experiments.empty()) {
gpr_log(GPR_INFO, "gRPC experiments: %s",
absl::StrJoin(experiment_status, ", ", absl::PairFormatter(":"))
.c_str());
} else {
gpr_log(GPR_INFO, "gRPC experiments: %s; default-enabled: %s",
absl::StrJoin(experiment_status, ", ", absl::PairFormatter(":"))
.c_str(),
absl::StrJoin(defaulted_on_experiments, ", ").c_str());
}
}
}
void ForceEnableExperiment(absl::string_view experiment, bool enable) {
GPR_ASSERT(g_loaded.load(std::memory_order_relaxed) == false);
GPR_ASSERT(Loaded()->load(std::memory_order_relaxed) == false);
for (size_t i = 0; i < kNumExperiments; i++) {
if (g_experiment_metadata[i].name != experiment) continue;
if (g_forced_experiments[i].forced) {
GPR_ASSERT(g_forced_experiments[i].value == enable);
if (ForcedExperiments()[i].forced) {
GPR_ASSERT(ForcedExperiments()[i].value == enable);
} else {
g_forced_experiments[i].forced = true;
g_forced_experiments[i].value = enable;
ForcedExperiments()[i].forced = true;
ForcedExperiments()[i].value = enable;
}
return;
}

@ -24,8 +24,6 @@
#if defined(GRPC_CFSTREAM)
namespace {
const char* const description_absl_base64 = "Use abseil base64 functions.";
const char* const additional_constraints_absl_base64 = "{}";
const char* const description_call_status_override_on_cancellation =
"Avoid overriding call status of successfully finished calls if it races "
"with cancellation.";
@ -98,18 +96,12 @@ const char* const additional_constraints_chaotic_good = "{}";
const uint8_t required_experiments_chaotic_good[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedClientCall),
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedServerCall)};
const char* const description_registered_method_lookup_in_transport =
"Change registered method's lookup point to transport";
const char* const additional_constraints_registered_method_lookup_in_transport =
"{}";
const char* const description_promise_based_inproc_transport =
"Use promises for the in-process transport.";
const char* const additional_constraints_promise_based_inproc_transport = "{}";
const uint8_t required_experiments_promise_based_inproc_transport[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedClientCall),
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedServerCall),
static_cast<uint8_t>(
grpc_core::kExperimentIdRegisteredMethodLookupInTransport)};
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedServerCall)};
const char* const description_rstpit =
"On RST_STREAM on a server, reduce MAX_CONCURRENT_STREAMS for a short "
"duration";
@ -142,12 +134,6 @@ const char* const additional_constraints_v3_backend_metric_filter = "{}";
const char* const description_v3_channel_idle_filters =
"Use the v3 filter API version of the idle filters.";
const char* const additional_constraints_v3_channel_idle_filters = "{}";
const char* const description_v3_compression_filter =
"Use the compression filter utilizing the v3 filter api";
const char* const additional_constraints_v3_compression_filter = "{}";
const char* const description_v3_server_auth_filter =
"Use the server auth filter utilizing the v3 filter api";
const char* const additional_constraints_v3_server_auth_filter = "{}";
const char* const description_work_serializer_clears_time_cache =
"Have the work serializer clear the time cache when it dispatches work.";
const char* const additional_constraints_work_serializer_clears_time_cache =
@ -169,8 +155,6 @@ const bool kDefaultForDebugOnly = true;
namespace grpc_core {
const ExperimentMetadata g_experiment_metadata[] = {
{"absl_base64", description_absl_base64, additional_constraints_absl_base64,
nullptr, 0, true, true},
{"call_status_override_on_cancellation",
description_call_status_override_on_cancellation,
additional_constraints_call_status_override_on_cancellation, nullptr, 0,
@ -211,14 +195,10 @@ const ExperimentMetadata g_experiment_metadata[] = {
{"chaotic_good", description_chaotic_good,
additional_constraints_chaotic_good, required_experiments_chaotic_good, 2,
false, true},
{"registered_method_lookup_in_transport",
description_registered_method_lookup_in_transport,
additional_constraints_registered_method_lookup_in_transport, nullptr, 0,
true, true},
{"promise_based_inproc_transport",
description_promise_based_inproc_transport,
additional_constraints_promise_based_inproc_transport,
required_experiments_promise_based_inproc_transport, 3, false, false},
required_experiments_promise_based_inproc_transport, 2, false, false},
{"rstpit", description_rstpit, additional_constraints_rstpit, nullptr, 0,
false, true},
{"schedule_cancellation_over_write",
@ -241,10 +221,6 @@ const ExperimentMetadata g_experiment_metadata[] = {
additional_constraints_v3_backend_metric_filter, nullptr, 0, false, true},
{"v3_channel_idle_filters", description_v3_channel_idle_filters,
additional_constraints_v3_channel_idle_filters, nullptr, 0, false, true},
{"v3_compression_filter", description_v3_compression_filter,
additional_constraints_v3_compression_filter, nullptr, 0, false, true},
{"v3_server_auth_filter", description_v3_server_auth_filter,
additional_constraints_v3_server_auth_filter, nullptr, 0, false, true},
{"work_serializer_clears_time_cache",
description_work_serializer_clears_time_cache,
additional_constraints_work_serializer_clears_time_cache, nullptr, 0, true,
@ -258,8 +234,6 @@ const ExperimentMetadata g_experiment_metadata[] = {
#elif defined(GPR_WINDOWS)
namespace {
const char* const description_absl_base64 = "Use abseil base64 functions.";
const char* const additional_constraints_absl_base64 = "{}";
const char* const description_call_status_override_on_cancellation =
"Avoid overriding call status of successfully finished calls if it races "
"with cancellation.";
@ -332,18 +306,12 @@ const char* const additional_constraints_chaotic_good = "{}";
const uint8_t required_experiments_chaotic_good[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedClientCall),
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedServerCall)};
const char* const description_registered_method_lookup_in_transport =
"Change registered method's lookup point to transport";
const char* const additional_constraints_registered_method_lookup_in_transport =
"{}";
const char* const description_promise_based_inproc_transport =
"Use promises for the in-process transport.";
const char* const additional_constraints_promise_based_inproc_transport = "{}";
const uint8_t required_experiments_promise_based_inproc_transport[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedClientCall),
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedServerCall),
static_cast<uint8_t>(
grpc_core::kExperimentIdRegisteredMethodLookupInTransport)};
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedServerCall)};
const char* const description_rstpit =
"On RST_STREAM on a server, reduce MAX_CONCURRENT_STREAMS for a short "
"duration";
@ -376,12 +344,6 @@ const char* const additional_constraints_v3_backend_metric_filter = "{}";
const char* const description_v3_channel_idle_filters =
"Use the v3 filter API version of the idle filters.";
const char* const additional_constraints_v3_channel_idle_filters = "{}";
const char* const description_v3_compression_filter =
"Use the compression filter utilizing the v3 filter api";
const char* const additional_constraints_v3_compression_filter = "{}";
const char* const description_v3_server_auth_filter =
"Use the server auth filter utilizing the v3 filter api";
const char* const additional_constraints_v3_server_auth_filter = "{}";
const char* const description_work_serializer_clears_time_cache =
"Have the work serializer clear the time cache when it dispatches work.";
const char* const additional_constraints_work_serializer_clears_time_cache =
@ -403,8 +365,6 @@ const bool kDefaultForDebugOnly = true;
namespace grpc_core {
const ExperimentMetadata g_experiment_metadata[] = {
{"absl_base64", description_absl_base64, additional_constraints_absl_base64,
nullptr, 0, true, true},
{"call_status_override_on_cancellation",
description_call_status_override_on_cancellation,
additional_constraints_call_status_override_on_cancellation, nullptr, 0,
@ -445,14 +405,10 @@ const ExperimentMetadata g_experiment_metadata[] = {
{"chaotic_good", description_chaotic_good,
additional_constraints_chaotic_good, required_experiments_chaotic_good, 2,
false, true},
{"registered_method_lookup_in_transport",
description_registered_method_lookup_in_transport,
additional_constraints_registered_method_lookup_in_transport, nullptr, 0,
true, true},
{"promise_based_inproc_transport",
description_promise_based_inproc_transport,
additional_constraints_promise_based_inproc_transport,
required_experiments_promise_based_inproc_transport, 3, false, false},
required_experiments_promise_based_inproc_transport, 2, false, false},
{"rstpit", description_rstpit, additional_constraints_rstpit, nullptr, 0,
false, true},
{"schedule_cancellation_over_write",
@ -475,10 +431,6 @@ const ExperimentMetadata g_experiment_metadata[] = {
additional_constraints_v3_backend_metric_filter, nullptr, 0, false, true},
{"v3_channel_idle_filters", description_v3_channel_idle_filters,
additional_constraints_v3_channel_idle_filters, nullptr, 0, false, true},
{"v3_compression_filter", description_v3_compression_filter,
additional_constraints_v3_compression_filter, nullptr, 0, false, true},
{"v3_server_auth_filter", description_v3_server_auth_filter,
additional_constraints_v3_server_auth_filter, nullptr, 0, false, true},
{"work_serializer_clears_time_cache",
description_work_serializer_clears_time_cache,
additional_constraints_work_serializer_clears_time_cache, nullptr, 0, true,
@ -492,8 +444,6 @@ const ExperimentMetadata g_experiment_metadata[] = {
#else
namespace {
const char* const description_absl_base64 = "Use abseil base64 functions.";
const char* const additional_constraints_absl_base64 = "{}";
const char* const description_call_status_override_on_cancellation =
"Avoid overriding call status of successfully finished calls if it races "
"with cancellation.";
@ -566,18 +516,12 @@ const char* const additional_constraints_chaotic_good = "{}";
const uint8_t required_experiments_chaotic_good[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedClientCall),
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedServerCall)};
const char* const description_registered_method_lookup_in_transport =
"Change registered method's lookup point to transport";
const char* const additional_constraints_registered_method_lookup_in_transport =
"{}";
const char* const description_promise_based_inproc_transport =
"Use promises for the in-process transport.";
const char* const additional_constraints_promise_based_inproc_transport = "{}";
const uint8_t required_experiments_promise_based_inproc_transport[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedClientCall),
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedServerCall),
static_cast<uint8_t>(
grpc_core::kExperimentIdRegisteredMethodLookupInTransport)};
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedServerCall)};
const char* const description_rstpit =
"On RST_STREAM on a server, reduce MAX_CONCURRENT_STREAMS for a short "
"duration";
@ -610,12 +554,6 @@ const char* const additional_constraints_v3_backend_metric_filter = "{}";
const char* const description_v3_channel_idle_filters =
"Use the v3 filter API version of the idle filters.";
const char* const additional_constraints_v3_channel_idle_filters = "{}";
const char* const description_v3_compression_filter =
"Use the compression filter utilizing the v3 filter api";
const char* const additional_constraints_v3_compression_filter = "{}";
const char* const description_v3_server_auth_filter =
"Use the server auth filter utilizing the v3 filter api";
const char* const additional_constraints_v3_server_auth_filter = "{}";
const char* const description_work_serializer_clears_time_cache =
"Have the work serializer clear the time cache when it dispatches work.";
const char* const additional_constraints_work_serializer_clears_time_cache =
@ -637,8 +575,6 @@ const bool kDefaultForDebugOnly = true;
namespace grpc_core {
const ExperimentMetadata g_experiment_metadata[] = {
{"absl_base64", description_absl_base64, additional_constraints_absl_base64,
nullptr, 0, true, true},
{"call_status_override_on_cancellation",
description_call_status_override_on_cancellation,
additional_constraints_call_status_override_on_cancellation, nullptr, 0,
@ -679,14 +615,10 @@ const ExperimentMetadata g_experiment_metadata[] = {
{"chaotic_good", description_chaotic_good,
additional_constraints_chaotic_good, required_experiments_chaotic_good, 2,
false, true},
{"registered_method_lookup_in_transport",
description_registered_method_lookup_in_transport,
additional_constraints_registered_method_lookup_in_transport, nullptr, 0,
true, true},
{"promise_based_inproc_transport",
description_promise_based_inproc_transport,
additional_constraints_promise_based_inproc_transport,
required_experiments_promise_based_inproc_transport, 3, false, false},
required_experiments_promise_based_inproc_transport, 2, false, false},
{"rstpit", description_rstpit, additional_constraints_rstpit, nullptr, 0,
false, true},
{"schedule_cancellation_over_write",
@ -709,10 +641,6 @@ const ExperimentMetadata g_experiment_metadata[] = {
additional_constraints_v3_backend_metric_filter, nullptr, 0, false, true},
{"v3_channel_idle_filters", description_v3_channel_idle_filters,
additional_constraints_v3_channel_idle_filters, nullptr, 0, false, true},
{"v3_compression_filter", description_v3_compression_filter,
additional_constraints_v3_compression_filter, nullptr, 0, false, true},
{"v3_server_auth_filter", description_v3_server_auth_filter,
additional_constraints_v3_server_auth_filter, nullptr, 0, false, true},
{"work_serializer_clears_time_cache",
description_work_serializer_clears_time_cache,
additional_constraints_work_serializer_clears_time_cache, nullptr, 0, true,

@ -57,8 +57,6 @@ namespace grpc_core {
#ifdef GRPC_EXPERIMENTS_ARE_FINAL
#if defined(GRPC_CFSTREAM)
#define GRPC_EXPERIMENT_IS_INCLUDED_ABSL_BASE64
inline bool IsAbslBase64Enabled() { return true; }
#ifndef NDEBUG
#define GRPC_EXPERIMENT_IS_INCLUDED_CALL_STATUS_OVERRIDE_ON_CANCELLATION
#endif
@ -89,8 +87,6 @@ inline bool IsPendingQueueCapEnabled() { return true; }
inline bool IsPromiseBasedClientCallEnabled() { return false; }
inline bool IsPromiseBasedServerCallEnabled() { return false; }
inline bool IsChaoticGoodEnabled() { return false; }
#define GRPC_EXPERIMENT_IS_INCLUDED_REGISTERED_METHOD_LOOKUP_IN_TRANSPORT
inline bool IsRegisteredMethodLookupInTransportEnabled() { return true; }
inline bool IsPromiseBasedInprocTransportEnabled() { return false; }
inline bool IsRstpitEnabled() { return false; }
inline bool IsScheduleCancellationOverWriteEnabled() { return false; }
@ -101,15 +97,11 @@ inline bool IsTraceRecordCallopsEnabled() { return false; }
inline bool IsUnconstrainedMaxQuotaBufferSizeEnabled() { return false; }
inline bool IsV3BackendMetricFilterEnabled() { return false; }
inline bool IsV3ChannelIdleFiltersEnabled() { return false; }
inline bool IsV3CompressionFilterEnabled() { return false; }
inline bool IsV3ServerAuthFilterEnabled() { return false; }
#define GRPC_EXPERIMENT_IS_INCLUDED_WORK_SERIALIZER_CLEARS_TIME_CACHE
inline bool IsWorkSerializerClearsTimeCacheEnabled() { return true; }
inline bool IsWorkSerializerDispatchEnabled() { return false; }
#elif defined(GPR_WINDOWS)
#define GRPC_EXPERIMENT_IS_INCLUDED_ABSL_BASE64
inline bool IsAbslBase64Enabled() { return true; }
#ifndef NDEBUG
#define GRPC_EXPERIMENT_IS_INCLUDED_CALL_STATUS_OVERRIDE_ON_CANCELLATION
#endif
@ -141,8 +133,6 @@ inline bool IsPendingQueueCapEnabled() { return true; }
inline bool IsPromiseBasedClientCallEnabled() { return false; }
inline bool IsPromiseBasedServerCallEnabled() { return false; }
inline bool IsChaoticGoodEnabled() { return false; }
#define GRPC_EXPERIMENT_IS_INCLUDED_REGISTERED_METHOD_LOOKUP_IN_TRANSPORT
inline bool IsRegisteredMethodLookupInTransportEnabled() { return true; }
inline bool IsPromiseBasedInprocTransportEnabled() { return false; }
inline bool IsRstpitEnabled() { return false; }
inline bool IsScheduleCancellationOverWriteEnabled() { return false; }
@ -153,15 +143,11 @@ inline bool IsTraceRecordCallopsEnabled() { return false; }
inline bool IsUnconstrainedMaxQuotaBufferSizeEnabled() { return false; }
inline bool IsV3BackendMetricFilterEnabled() { return false; }
inline bool IsV3ChannelIdleFiltersEnabled() { return false; }
inline bool IsV3CompressionFilterEnabled() { return false; }
inline bool IsV3ServerAuthFilterEnabled() { return false; }
#define GRPC_EXPERIMENT_IS_INCLUDED_WORK_SERIALIZER_CLEARS_TIME_CACHE
inline bool IsWorkSerializerClearsTimeCacheEnabled() { return true; }
inline bool IsWorkSerializerDispatchEnabled() { return false; }
#else
#define GRPC_EXPERIMENT_IS_INCLUDED_ABSL_BASE64
inline bool IsAbslBase64Enabled() { return true; }
#ifndef NDEBUG
#define GRPC_EXPERIMENT_IS_INCLUDED_CALL_STATUS_OVERRIDE_ON_CANCELLATION
#endif
@ -194,8 +180,6 @@ inline bool IsPendingQueueCapEnabled() { return true; }
inline bool IsPromiseBasedClientCallEnabled() { return false; }
inline bool IsPromiseBasedServerCallEnabled() { return false; }
inline bool IsChaoticGoodEnabled() { return false; }
#define GRPC_EXPERIMENT_IS_INCLUDED_REGISTERED_METHOD_LOOKUP_IN_TRANSPORT
inline bool IsRegisteredMethodLookupInTransportEnabled() { return true; }
inline bool IsPromiseBasedInprocTransportEnabled() { return false; }
inline bool IsRstpitEnabled() { return false; }
inline bool IsScheduleCancellationOverWriteEnabled() { return false; }
@ -206,8 +190,6 @@ inline bool IsTraceRecordCallopsEnabled() { return false; }
inline bool IsUnconstrainedMaxQuotaBufferSizeEnabled() { return false; }
inline bool IsV3BackendMetricFilterEnabled() { return false; }
inline bool IsV3ChannelIdleFiltersEnabled() { return false; }
inline bool IsV3CompressionFilterEnabled() { return false; }
inline bool IsV3ServerAuthFilterEnabled() { return false; }
#define GRPC_EXPERIMENT_IS_INCLUDED_WORK_SERIALIZER_CLEARS_TIME_CACHE
inline bool IsWorkSerializerClearsTimeCacheEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_WORK_SERIALIZER_DISPATCH
@ -216,7 +198,6 @@ inline bool IsWorkSerializerDispatchEnabled() { return true; }
#else
enum ExperimentIds {
kExperimentIdAbslBase64,
kExperimentIdCallStatusOverrideOnCancellation,
kExperimentIdCallV3,
kExperimentIdCanaryClientPrivacy,
@ -235,7 +216,6 @@ enum ExperimentIds {
kExperimentIdPromiseBasedClientCall,
kExperimentIdPromiseBasedServerCall,
kExperimentIdChaoticGood,
kExperimentIdRegisteredMethodLookupInTransport,
kExperimentIdPromiseBasedInprocTransport,
kExperimentIdRstpit,
kExperimentIdScheduleCancellationOverWrite,
@ -246,16 +226,10 @@ enum ExperimentIds {
kExperimentIdUnconstrainedMaxQuotaBufferSize,
kExperimentIdV3BackendMetricFilter,
kExperimentIdV3ChannelIdleFilters,
kExperimentIdV3CompressionFilter,
kExperimentIdV3ServerAuthFilter,
kExperimentIdWorkSerializerClearsTimeCache,
kExperimentIdWorkSerializerDispatch,
kNumExperiments
};
#define GRPC_EXPERIMENT_IS_INCLUDED_ABSL_BASE64
inline bool IsAbslBase64Enabled() {
return IsExperimentEnabled(kExperimentIdAbslBase64);
}
#define GRPC_EXPERIMENT_IS_INCLUDED_CALL_STATUS_OVERRIDE_ON_CANCELLATION
inline bool IsCallStatusOverrideOnCancellationEnabled() {
return IsExperimentEnabled(kExperimentIdCallStatusOverrideOnCancellation);
@ -328,10 +302,6 @@ inline bool IsPromiseBasedServerCallEnabled() {
inline bool IsChaoticGoodEnabled() {
return IsExperimentEnabled(kExperimentIdChaoticGood);
}
#define GRPC_EXPERIMENT_IS_INCLUDED_REGISTERED_METHOD_LOOKUP_IN_TRANSPORT
inline bool IsRegisteredMethodLookupInTransportEnabled() {
return IsExperimentEnabled(kExperimentIdRegisteredMethodLookupInTransport);
}
#define GRPC_EXPERIMENT_IS_INCLUDED_PROMISE_BASED_INPROC_TRANSPORT
inline bool IsPromiseBasedInprocTransportEnabled() {
return IsExperimentEnabled(kExperimentIdPromiseBasedInprocTransport);
@ -372,14 +342,6 @@ inline bool IsV3BackendMetricFilterEnabled() {
inline bool IsV3ChannelIdleFiltersEnabled() {
return IsExperimentEnabled(kExperimentIdV3ChannelIdleFilters);
}
#define GRPC_EXPERIMENT_IS_INCLUDED_V3_COMPRESSION_FILTER
inline bool IsV3CompressionFilterEnabled() {
return IsExperimentEnabled(kExperimentIdV3CompressionFilter);
}
#define GRPC_EXPERIMENT_IS_INCLUDED_V3_SERVER_AUTH_FILTER
inline bool IsV3ServerAuthFilterEnabled() {
return IsExperimentEnabled(kExperimentIdV3ServerAuthFilter);
}
#define GRPC_EXPERIMENT_IS_INCLUDED_WORK_SERIALIZER_CLEARS_TIME_CACHE
inline bool IsWorkSerializerClearsTimeCacheEnabled() {
return IsExperimentEnabled(kExperimentIdWorkSerializerClearsTimeCache);

@ -40,11 +40,6 @@
# This file only defines the experiments. Refer to rollouts.yaml for the rollout
# state of each experiment.
- name: absl_base64
description: Use abseil base64 functions.
expiry: 2024/06/01
owner: roth@google.com
test_tags: ["credential_token_tests"]
- name: call_status_override_on_cancellation
description:
Avoid overriding call status of successfully finished calls if it races with
@ -80,21 +75,21 @@
allow_in_fuzzing_config: false
- name: event_engine_client
description: Use EventEngine clients instead of iomgr's grpc_tcp_client
expiry: 2024/04/01
expiry: 2024/07/01
owner: hork@google.com
test_tags: ["core_end2end_test", "event_engine_client_test"]
uses_polling: true
- name: event_engine_dns
description:
If set, use EventEngine DNSResolver for client channel resolution
expiry: 2024/04/01
expiry: 2024/07/01
owner: yijiem@google.com
test_tags: ["cancel_ares_query_test", "resolver_component_tests_runner_invoker"]
allow_in_fuzzing_config: false
uses_polling: true
- name: event_engine_listener
description: Use EventEngine listeners instead of iomgr's grpc_tcp_server
expiry: 2024/04/01
expiry: 2024/07/01
owner: vigneshbabu@google.com
test_tags: ["core_end2end_test", "event_engine_listener_test"]
uses_polling: true
@ -170,7 +165,7 @@
owner: ctiller@google.com
test_tags: []
allow_in_fuzzing_config: false # experiment currently crashes if enabled
requires: [promise_based_client_call, promise_based_server_call, registered_method_lookup_in_transport]
requires: [promise_based_client_call, promise_based_server_call]
- name: promise_based_server_call
description:
If set, use the new gRPC promise based call code when it's appropriate
@ -178,12 +173,6 @@
expiry: 2024/06/14
owner: ctiller@google.com
test_tags: ["core_end2end_test", "cpp_end2end_test", "xds_end2end_test", "logging_test"]
- name: registered_method_lookup_in_transport
description:
Change registered method's lookup point to transport
expiry: 2024/03/31
owner: yashkt@google.com
test_tags: ["surface_registered_method_lookup"]
- name: rstpit
description:
On RST_STREAM on a server, reduce MAX_CONCURRENT_STREAMS for a short duration
@ -235,25 +224,13 @@
- name: v3_channel_idle_filters
description:
Use the v3 filter API version of the idle filters.
expiry: 2024/04/04
owner: ctiller@google.com
test_tags: []
- name: v3_compression_filter
description:
Use the compression filter utilizing the v3 filter api
expiry: 2024/04/04
owner: ctiller@google.com
test_tags: ["compression_test"]
- name: v3_server_auth_filter
description:
Use the server auth filter utilizing the v3 filter api
expiry: 2024/04/04
expiry: 2024/07/04
owner: ctiller@google.com
test_tags: []
- name: work_serializer_clears_time_cache
description:
Have the work serializer clear the time cache when it dispatches work.
expiry: 2024/04/01
expiry: 2024/07/01
owner: ctiller@google.com
test_tags: []
- name: work_serializer_dispatch
@ -261,6 +238,6 @@
Have the work serializer dispatch work to event engine for every callback,
instead of running things inline in the first thread that successfully
enqueues work.
expiry: 2024/03/31
expiry: 2024/06/30
owner: ysseung@google.com
test_tags: ["core_end2end_test", "cpp_end2end_test", "xds_end2end_test", "lb_unit_test"]

@ -40,8 +40,6 @@
#
# Supported platforms: ios, windows, posix
- name: absl_base64
default: true
- name: call_status_override_on_cancellation
default: debug
- name: call_v3
@ -98,8 +96,6 @@
posix: false
- name: promise_based_server_call
default: false
- name: registered_method_lookup_in_transport
default: true
- name: rstpit
default: false
- name: schedule_cancellation_over_write

@ -31,6 +31,7 @@
#include <grpc/support/log.h>
#include "src/core/lib/event_engine/event_engine_context.h"
#include "src/core/lib/gprpp/construct_destruct.h"
#include "src/core/lib/gprpp/no_destruct.h"
#include "src/core/lib/gprpp/orphanable.h"

@ -20,7 +20,7 @@
#include <grpc/event_engine/event_engine.h>
#include "src/core/lib/event_engine/default_event_engine.h" // IWYU pragma: keep
#include "src/core/lib/event_engine/event_engine_context.h" // IWYU pragma: keep
#include "src/core/lib/gprpp/time.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/promise/activity.h"

@ -42,12 +42,10 @@
#include <grpc/support/string_util.h>
#include <grpc/support/time.h>
#include "src/core/lib/experiments/experiments.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/json/json_reader.h"
#include "src/core/lib/json/json_writer.h"
#include "src/core/lib/security/util/json_util.h"
#include "src/core/lib/slice/b64.h"
using grpc_core::Json;
@ -183,9 +181,6 @@ static char* encoded_jwt_header(const char* key_id, const char* algorithm) {
{"kid", Json::FromString(key_id)},
});
std::string json_str = grpc_core::JsonDump(json);
if (!grpc_core::IsAbslBase64Enabled()) {
return grpc_base64_encode(json_str.c_str(), json_str.size(), 1, 0);
}
return gpr_strdup(absl::WebSafeBase64Escape(json_str).c_str());
}
@ -214,9 +209,6 @@ static char* encoded_jwt_claim(const grpc_auth_json_key* json_key,
std::string json_str =
grpc_core::JsonDump(Json::FromObject(std::move(object)));
if (!grpc_core::IsAbslBase64Enabled()) {
return grpc_base64_encode(json_str.c_str(), json_str.size(), 1, 0);
}
return gpr_strdup(absl::WebSafeBase64Escape(json_str).c_str());
}
@ -289,14 +281,10 @@ char* compute_and_encode_signature(const grpc_auth_json_key* json_key,
gpr_log(GPR_ERROR, "DigestFinal (signature compute) failed.");
goto end;
}
if (!grpc_core::IsAbslBase64Enabled()) {
result = grpc_base64_encode(sig, sig_len, 1, 0);
} else {
result =
gpr_strdup(absl::WebSafeBase64Escape(
absl::string_view(reinterpret_cast<char*>(sig), sig_len))
.c_str());
}
result =
gpr_strdup(absl::WebSafeBase64Escape(
absl::string_view(reinterpret_cast<char*>(sig), sig_len))
.c_str());
end:
#if OPENSSL_VERSION_NUMBER < 0x30000000L

@ -53,7 +53,6 @@
#include <grpc/support/string_util.h>
#include <grpc/support/time.h>
#include "src/core/lib/experiments/experiments.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/manual_constructor.h"
#include "src/core/lib/gprpp/memory.h"
@ -68,7 +67,6 @@
#include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/json/json_reader.h"
#include "src/core/lib/security/credentials/credentials.h" // IWYU pragma: keep
#include "src/core/lib/slice/b64.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/uri/uri_parser.h"
@ -114,19 +112,9 @@ static const EVP_MD* evp_md_from_alg(const char* alg) {
static Json parse_json_part_from_jwt(const char* str, size_t len) {
std::string string;
if (!grpc_core::IsAbslBase64Enabled()) {
grpc_slice slice = grpc_base64_decode_with_len(str, len, 1);
if (GRPC_SLICE_IS_EMPTY(slice)) {
gpr_log(GPR_ERROR, "Invalid base64.");
return Json(); // JSON null
}
string = std::string(grpc_core::StringViewFromSlice(slice));
grpc_core::CSliceUnref(slice);
} else {
if (!absl::WebSafeBase64Unescape(absl::string_view(str, len), &string)) {
gpr_log(GPR_ERROR, "Invalid base64.");
return Json(); // JSON null
}
if (!absl::WebSafeBase64Unescape(absl::string_view(str, len), &string)) {
gpr_log(GPR_ERROR, "Invalid base64.");
return Json(); // JSON null
}
auto json = grpc_core::JsonParse(string);
if (!json.ok()) {
@ -491,18 +479,6 @@ end:
static BIGNUM* bignum_from_base64(const char* b64) {
if (b64 == nullptr) return nullptr;
if (!grpc_core::IsAbslBase64Enabled()) {
grpc_slice bin = grpc_base64_decode(b64, 1);
if (GRPC_SLICE_IS_EMPTY(bin)) {
gpr_log(GPR_ERROR, "Invalid base64 for big num.");
return nullptr;
}
BIGNUM* result =
BN_bin2bn(GRPC_SLICE_START_PTR(bin),
TSI_SIZE_AS_SIZE(GRPC_SLICE_LENGTH(bin)), nullptr);
grpc_core::CSliceUnref(bin);
return result;
}
std::string string;
if (!absl::WebSafeBase64Unescape(b64, &string)) {
gpr_log(GPR_ERROR, "Invalid base64 for big num.");
@ -948,6 +924,7 @@ void grpc_jwt_verifier_verify(grpc_jwt_verifier* verifier,
size_t signed_jwt_len;
const char* cur = jwt;
Json json;
std::string signature_str;
GPR_ASSERT(verifier != nullptr && jwt != nullptr && audience != nullptr &&
cb != nullptr);
@ -969,14 +946,8 @@ void grpc_jwt_verifier_verify(grpc_jwt_verifier* verifier,
signed_jwt_len = static_cast<size_t>(dot - jwt);
cur = dot + 1;
if (!grpc_core::IsAbslBase64Enabled()) {
signature = grpc_base64_decode(cur, 1);
if (GRPC_SLICE_IS_EMPTY(signature)) goto error;
} else {
std::string signature_str;
if (!absl::WebSafeBase64Unescape(cur, &signature_str)) goto error;
signature = grpc_slice_from_cpp_string(std::move(signature_str));
}
if (!absl::WebSafeBase64Unescape(cur, &signature_str)) goto error;
signature = grpc_slice_from_cpp_string(std::move(signature_str));
retrieve_key_and_verify(
verifier_cb_ctx_create(verifier, pollset, header, claims, audience,
signature, jwt, signed_jwt_len, user_data, cb));

@ -62,31 +62,6 @@ class ClientAuthFilter final : public ChannelFilter {
grpc_call_credentials::GetRequestMetadataArgs args_;
};
class LegacyServerAuthFilter final : public ChannelFilter {
public:
static const grpc_channel_filter kFilter;
static absl::StatusOr<LegacyServerAuthFilter> Create(const ChannelArgs& args,
ChannelFilter::Args);
// Construct a promise for one call.
ArenaPromise<ServerMetadataHandle> MakeCallPromise(
CallArgs call_args, NextPromiseFactory next_promise_factory) override;
private:
LegacyServerAuthFilter(
RefCountedPtr<grpc_server_credentials> server_credentials,
RefCountedPtr<grpc_auth_context> auth_context);
class RunApplicationCode;
ArenaPromise<absl::StatusOr<CallArgs>> GetCallCredsMetadata(
CallArgs call_args);
RefCountedPtr<grpc_server_credentials> server_credentials_;
RefCountedPtr<grpc_auth_context> auth_context_;
};
class ServerAuthFilter final : public ImplementChannelFilter<ServerAuthFilter> {
private:
ServerAuthFilter(RefCountedPtr<grpc_server_credentials> server_credentials,

@ -1,244 +0,0 @@
//
//
// Copyright 2015 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 <algorithm>
#include <atomic>
#include <cstddef>
#include <functional>
#include <memory>
#include <utility>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include <grpc/grpc.h>
#include <grpc/grpc_security.h>
#include <grpc/status.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/channel/channel_args.h"
#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/promise_based_filter.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/gprpp/status_helper.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/promise/activity.h"
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/promise/context.h"
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/promise/try_seq.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/security/context/security_context.h"
#include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/security/transport/auth_filters.h" // IWYU pragma: keep
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/surface/call_trace.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/transport.h"
namespace grpc_core {
const grpc_channel_filter LegacyServerAuthFilter::kFilter =
MakePromiseBasedFilter<LegacyServerAuthFilter, FilterEndpoint::kServer>(
"server-auth");
namespace {
class ArrayEncoder {
public:
explicit ArrayEncoder(grpc_metadata_array* result) : result_(result) {}
void Encode(const Slice& key, const Slice& value) {
Append(key.Ref(), value.Ref());
}
template <typename Which>
void Encode(Which, const typename Which::ValueType& value) {
Append(Slice(StaticSlice::FromStaticString(Which::key())),
Slice(Which::Encode(value)));
}
void Encode(HttpMethodMetadata,
const typename HttpMethodMetadata::ValueType&) {}
private:
void Append(Slice key, Slice value) {
if (result_->count == result_->capacity) {
result_->capacity =
std::max(result_->capacity + 8, result_->capacity * 2);
result_->metadata = static_cast<grpc_metadata*>(gpr_realloc(
result_->metadata, result_->capacity * sizeof(grpc_metadata)));
}
auto* usr_md = &result_->metadata[result_->count++];
usr_md->key = key.TakeCSlice();
usr_md->value = value.TakeCSlice();
}
grpc_metadata_array* result_;
};
// TODO(ctiller): seek out all users of this functionality and change API so
// that this unilateral format conversion IS NOT REQUIRED.
grpc_metadata_array MetadataBatchToMetadataArray(
const grpc_metadata_batch* batch) {
grpc_metadata_array result;
grpc_metadata_array_init(&result);
ArrayEncoder encoder(&result);
batch->Encode(&encoder);
return result;
}
} // namespace
class LegacyServerAuthFilter::RunApplicationCode {
public:
// TODO(ctiller): Allocate state_ into a pool on the arena to reuse this
// memory later
RunApplicationCode(LegacyServerAuthFilter* filter, CallArgs call_args)
: state_(GetContext<Arena>()->ManagedNew<State>(std::move(call_args))) {
if (grpc_call_trace.enabled()) {
gpr_log(GPR_ERROR,
"%s[server-auth]: Delegate to application: filter=%p this=%p "
"auth_ctx=%p",
GetContext<Activity>()->DebugTag().c_str(), filter, this,
filter->auth_context_.get());
}
filter->server_credentials_->auth_metadata_processor().process(
filter->server_credentials_->auth_metadata_processor().state,
filter->auth_context_.get(), state_->md.metadata, state_->md.count,
OnMdProcessingDone, state_);
}
RunApplicationCode(const RunApplicationCode&) = delete;
RunApplicationCode& operator=(const RunApplicationCode&) = delete;
RunApplicationCode(RunApplicationCode&& other) noexcept
: state_(std::exchange(other.state_, nullptr)) {}
RunApplicationCode& operator=(RunApplicationCode&& other) noexcept {
state_ = std::exchange(other.state_, nullptr);
return *this;
}
Poll<absl::StatusOr<CallArgs>> operator()() {
if (state_->done.load(std::memory_order_acquire)) {
return Poll<absl::StatusOr<CallArgs>>(std::move(state_->call_args));
}
return Pending{};
}
private:
struct State {
explicit State(CallArgs call_args) : call_args(std::move(call_args)) {}
Waker waker{GetContext<Activity>()->MakeOwningWaker()};
absl::StatusOr<CallArgs> call_args;
grpc_metadata_array md =
MetadataBatchToMetadataArray(call_args->client_initial_metadata.get());
std::atomic<bool> done{false};
};
// Called from application code.
static void OnMdProcessingDone(
void* user_data, const grpc_metadata* consumed_md, size_t num_consumed_md,
const grpc_metadata* response_md, size_t num_response_md,
grpc_status_code status, const char* error_details) {
ApplicationCallbackExecCtx callback_exec_ctx;
ExecCtx exec_ctx;
auto* state = static_cast<State*>(user_data);
// TODO(ZhenLian): Implement support for response_md.
if (response_md != nullptr && num_response_md > 0) {
gpr_log(GPR_ERROR,
"response_md in auth metadata processing not supported for now. "
"Ignoring...");
}
if (status == GRPC_STATUS_OK) {
ClientMetadataHandle& md = state->call_args->client_initial_metadata;
for (size_t i = 0; i < num_consumed_md; i++) {
md->Remove(StringViewFromSlice(consumed_md[i].key));
}
} else {
if (error_details == nullptr) {
error_details = "Authentication metadata processing failed.";
}
state->call_args = grpc_error_set_int(
absl::Status(static_cast<absl::StatusCode>(status), error_details),
StatusIntProperty::kRpcStatus, status);
}
// Clean up.
for (size_t i = 0; i < state->md.count; i++) {
CSliceUnref(state->md.metadata[i].key);
CSliceUnref(state->md.metadata[i].value);
}
grpc_metadata_array_destroy(&state->md);
auto waker = std::move(state->waker);
state->done.store(true, std::memory_order_release);
waker.Wakeup();
}
State* state_;
};
ArenaPromise<ServerMetadataHandle> LegacyServerAuthFilter::MakeCallPromise(
CallArgs call_args, NextPromiseFactory next_promise_factory) {
// Create server security context. Set its auth context from channel
// data and save it in the call context.
grpc_server_security_context* server_ctx =
grpc_server_security_context_create(GetContext<Arena>());
server_ctx->auth_context =
auth_context_->Ref(DEBUG_LOCATION, "server_auth_filter");
grpc_call_context_element& context =
GetContext<grpc_call_context_element>()[GRPC_CONTEXT_SECURITY];
if (context.value != nullptr) context.destroy(context.value);
context.value = server_ctx;
context.destroy = grpc_server_security_context_destroy;
if (server_credentials_ == nullptr ||
server_credentials_->auth_metadata_processor().process == nullptr) {
return next_promise_factory(std::move(call_args));
}
return TrySeq(RunApplicationCode(this, std::move(call_args)),
std::move(next_promise_factory));
}
LegacyServerAuthFilter::LegacyServerAuthFilter(
RefCountedPtr<grpc_server_credentials> server_credentials,
RefCountedPtr<grpc_auth_context> auth_context)
: server_credentials_(server_credentials), auth_context_(auth_context) {}
absl::StatusOr<LegacyServerAuthFilter> LegacyServerAuthFilter::Create(
const ChannelArgs& args, ChannelFilter::Args) {
auto auth_context = args.GetObjectRef<grpc_auth_context>();
GPR_ASSERT(auth_context != nullptr);
auto creds = args.GetObjectRef<grpc_server_credentials>();
return LegacyServerAuthFilter(std::move(creds), std::move(auth_context));
}
} // namespace grpc_core

@ -1,239 +0,0 @@
//
//
// Copyright 2015 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/core/lib/slice/b64.h"
#include <stdint.h>
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/slice/slice.h"
// --- Constants. ---
static const int8_t base64_bytes[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, 0x3E, -1, -1, -1, 0x3F,
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, -1, -1,
-1, 0x7F, -1, -1, -1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, -1, -1, -1, -1, -1,
-1, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
0x31, 0x32, 0x33, -1, -1, -1, -1, -1};
static const char base64_url_unsafe_chars[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const char base64_url_safe_chars[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
#define GRPC_BASE64_PAD_CHAR '='
#define GRPC_BASE64_PAD_BYTE 0x7F
#define GRPC_BASE64_MULTILINE_LINE_LEN 76
#define GRPC_BASE64_MULTILINE_NUM_BLOCKS (GRPC_BASE64_MULTILINE_LINE_LEN / 4)
// --- base64 functions. ---
char* grpc_base64_encode(const void* vdata, size_t data_size, int url_safe,
int multiline) {
size_t result_projected_size =
grpc_base64_estimate_encoded_size(data_size, multiline);
char* result = static_cast<char*>(gpr_malloc(result_projected_size));
grpc_base64_encode_core(result, vdata, data_size, url_safe, multiline);
return result;
}
size_t grpc_base64_estimate_encoded_size(size_t data_size, int multiline) {
size_t result_projected_size =
4 * ((data_size + 3) / 3) +
2 * (multiline ? (data_size / (3 * GRPC_BASE64_MULTILINE_NUM_BLOCKS))
: 0) +
1;
return result_projected_size;
}
void grpc_base64_encode_core(char* result, const void* vdata, size_t data_size,
int url_safe, int multiline) {
const unsigned char* data = static_cast<const unsigned char*>(vdata);
const char* base64_chars =
url_safe ? base64_url_safe_chars : base64_url_unsafe_chars;
const size_t result_projected_size =
grpc_base64_estimate_encoded_size(data_size, multiline);
char* current = result;
size_t num_blocks = 0;
size_t i = 0;
// Encode each block.
while (data_size >= 3) {
*current++ = base64_chars[(data[i] >> 2) & 0x3F];
*current++ =
base64_chars[((data[i] & 0x03) << 4) | ((data[i + 1] >> 4) & 0x0F)];
*current++ =
base64_chars[((data[i + 1] & 0x0F) << 2) | ((data[i + 2] >> 6) & 0x03)];
*current++ = base64_chars[data[i + 2] & 0x3F];
data_size -= 3;
i += 3;
if (multiline && (++num_blocks == GRPC_BASE64_MULTILINE_NUM_BLOCKS)) {
*current++ = '\r';
*current++ = '\n';
num_blocks = 0;
}
}
// Take care of the tail.
if (data_size == 2) {
*current++ = base64_chars[(data[i] >> 2) & 0x3F];
*current++ =
base64_chars[((data[i] & 0x03) << 4) | ((data[i + 1] >> 4) & 0x0F)];
*current++ = base64_chars[(data[i + 1] & 0x0F) << 2];
*current++ = GRPC_BASE64_PAD_CHAR;
} else if (data_size == 1) {
*current++ = base64_chars[(data[i] >> 2) & 0x3F];
*current++ = base64_chars[(data[i] & 0x03) << 4];
*current++ = GRPC_BASE64_PAD_CHAR;
*current++ = GRPC_BASE64_PAD_CHAR;
}
GPR_ASSERT(current >= result);
GPR_ASSERT((uintptr_t)(current - result) < result_projected_size);
result[current - result] = '\0';
}
grpc_slice grpc_base64_decode(const char* b64, int url_safe) {
return grpc_base64_decode_with_len(b64, strlen(b64), url_safe);
}
static void decode_one_char(const unsigned char* codes, unsigned char* result,
size_t* result_offset) {
uint32_t packed = (static_cast<uint32_t>(codes[0]) << 2) |
(static_cast<uint32_t>(codes[1]) >> 4);
result[(*result_offset)++] = static_cast<unsigned char>(packed);
}
static void decode_two_chars(const unsigned char* codes, unsigned char* result,
size_t* result_offset) {
uint32_t packed = (static_cast<uint32_t>(codes[0]) << 10) |
(static_cast<uint32_t>(codes[1]) << 4) |
(static_cast<uint32_t>(codes[2]) >> 2);
result[(*result_offset)++] = static_cast<unsigned char>(packed >> 8);
result[(*result_offset)++] = static_cast<unsigned char>(packed);
}
static int decode_group(const unsigned char* codes, size_t num_codes,
unsigned char* result, size_t* result_offset) {
GPR_ASSERT(num_codes <= 4);
// Short end groups that may not have padding.
if (num_codes == 1) {
gpr_log(GPR_ERROR, "Invalid group. Must be at least 2 bytes.");
return 0;
}
if (num_codes == 2) {
decode_one_char(codes, result, result_offset);
return 1;
}
if (num_codes == 3) {
decode_two_chars(codes, result, result_offset);
return 1;
}
// Regular 4 byte groups with padding or not.
GPR_ASSERT(num_codes == 4);
if (codes[0] == GRPC_BASE64_PAD_BYTE || codes[1] == GRPC_BASE64_PAD_BYTE) {
gpr_log(GPR_ERROR, "Invalid padding detected.");
return 0;
}
if (codes[2] == GRPC_BASE64_PAD_BYTE) {
if (codes[3] == GRPC_BASE64_PAD_BYTE) {
decode_one_char(codes, result, result_offset);
} else {
gpr_log(GPR_ERROR, "Invalid padding detected.");
return 0;
}
} else if (codes[3] == GRPC_BASE64_PAD_BYTE) {
decode_two_chars(codes, result, result_offset);
} else {
// No padding.
uint32_t packed = (static_cast<uint32_t>(codes[0]) << 18) |
(static_cast<uint32_t>(codes[1]) << 12) |
(static_cast<uint32_t>(codes[2]) << 6) | codes[3];
result[(*result_offset)++] = static_cast<unsigned char>(packed >> 16);
result[(*result_offset)++] = static_cast<unsigned char>(packed >> 8);
result[(*result_offset)++] = static_cast<unsigned char>(packed);
}
return 1;
}
grpc_slice grpc_base64_decode_with_len(const char* b64, size_t b64_len,
int url_safe) {
grpc_slice result = GRPC_SLICE_MALLOC(b64_len);
unsigned char* current = GRPC_SLICE_START_PTR(result);
size_t result_size = 0;
unsigned char codes[4];
size_t num_codes = 0;
while (b64_len--) {
unsigned char c = static_cast<unsigned char>(*b64++);
signed char code;
if (c >= GPR_ARRAY_SIZE(base64_bytes)) continue;
if (url_safe) {
if (c == '+' || c == '/') {
gpr_log(GPR_ERROR, "Invalid character for url safe base64 %c", c);
goto fail;
}
if (c == '-') {
c = '+';
} else if (c == '_') {
c = '/';
}
}
code = base64_bytes[c];
if (code == -1) {
if (c != '\r' && c != '\n') {
gpr_log(GPR_ERROR, "Invalid character %c", c);
goto fail;
}
} else {
codes[num_codes++] = static_cast<unsigned char>(code);
if (num_codes == 4) {
if (!decode_group(codes, num_codes, current, &result_size)) goto fail;
num_codes = 0;
}
}
}
if (num_codes != 0 &&
!decode_group(codes, num_codes, current, &result_size)) {
goto fail;
}
GRPC_SLICE_SET_LENGTH(result, result_size);
return result;
fail:
grpc_core::CSliceUnref(result);
return grpc_empty_slice();
}

@ -1,52 +0,0 @@
//
//
// Copyright 2015 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_SLICE_B64_H
#define GRPC_SRC_CORE_LIB_SLICE_B64_H
#include <grpc/support/port_platform.h>
#include <stddef.h>
#include <grpc/slice.h>
// Encodes data using base64. It is the caller's responsibility to free
// the returned char * using gpr_free. Returns NULL on NULL input.
// TODO(makdharma) : change the flags to bool from int
char* grpc_base64_encode(const void* data, size_t data_size, int url_safe,
int multiline);
// estimate the upper bound on size of base64 encoded data. The actual size
// is guaranteed to be less than or equal to the size returned here.
size_t grpc_base64_estimate_encoded_size(size_t data_size, int multiline);
// Encodes data using base64 and write it to memory pointed to by result. It is
// the caller's responsibility to allocate enough memory in |result| to fit the
// encoded data.
void grpc_base64_encode_core(char* result, const void* vdata, size_t data_size,
int url_safe, int multiline);
// Decodes data according to the base64 specification. Returns an empty
// slice in case of failure.
grpc_slice grpc_base64_decode(const char* b64, int url_safe);
// Same as above except that the length is provided by the caller.
grpc_slice grpc_base64_decode_with_len(const char* b64, size_t b64_len,
int url_safe);
#endif // GRPC_SRC_CORE_LIB_SLICE_B64_H

@ -289,8 +289,10 @@ grpc_slice grpc_slice_sub(grpc_slice source, size_t begin, size_t end) {
return subset;
}
grpc_slice grpc_slice_split_tail_maybe_ref(grpc_slice* source, size_t split,
grpc_slice_ref_whom ref_whom) {
template <bool allow_inline>
grpc_slice grpc_slice_split_tail_maybe_ref_impl(grpc_slice* source,
size_t split,
grpc_slice_ref_whom ref_whom) {
grpc_slice tail;
if (source->refcount == nullptr) {
@ -311,7 +313,7 @@ grpc_slice grpc_slice_split_tail_maybe_ref(grpc_slice* source, size_t split,
} else {
size_t tail_length = source->data.refcounted.length - split;
GPR_ASSERT(source->data.refcounted.length >= split);
if (tail_length < sizeof(tail.data.inlined.bytes) &&
if (allow_inline && tail_length < sizeof(tail.data.inlined.bytes) &&
ref_whom != GRPC_SLICE_REF_TAIL) {
// Copy out the bytes - it'll be cheaper than refcounting
tail.refcount = nullptr;
@ -346,11 +348,27 @@ grpc_slice grpc_slice_split_tail_maybe_ref(grpc_slice* source, size_t split,
return tail;
}
grpc_slice grpc_slice_split_tail_maybe_ref(grpc_slice* source, size_t split,
grpc_slice_ref_whom ref_whom) {
return grpc_slice_split_tail_maybe_ref_impl<true>(source, split, ref_whom);
}
grpc_slice grpc_slice_split_tail_maybe_ref_no_inline(
grpc_slice* source, size_t split, grpc_slice_ref_whom ref_whom) {
return grpc_slice_split_tail_maybe_ref_impl<false>(source, split, ref_whom);
}
grpc_slice grpc_slice_split_tail(grpc_slice* source, size_t split) {
return grpc_slice_split_tail_maybe_ref(source, split, GRPC_SLICE_REF_BOTH);
}
grpc_slice grpc_slice_split_head(grpc_slice* source, size_t split) {
grpc_slice grpc_slice_split_tail_no_inline(grpc_slice* source, size_t split) {
return grpc_slice_split_tail_maybe_ref_no_inline(source, split,
GRPC_SLICE_REF_BOTH);
}
template <bool allow_inline>
grpc_slice grpc_slice_split_head_impl(grpc_slice* source, size_t split) {
grpc_slice head;
if (source->refcount == nullptr) {
@ -363,7 +381,7 @@ grpc_slice grpc_slice_split_head(grpc_slice* source, size_t split) {
static_cast<uint8_t>(source->data.inlined.length - split);
memmove(source->data.inlined.bytes, source->data.inlined.bytes + split,
source->data.inlined.length);
} else if (split < sizeof(head.data.inlined.bytes)) {
} else if (allow_inline && split < sizeof(head.data.inlined.bytes)) {
GPR_ASSERT(source->data.refcounted.length >= split);
head.refcount = nullptr;
@ -390,6 +408,14 @@ grpc_slice grpc_slice_split_head(grpc_slice* source, size_t split) {
return head;
}
grpc_slice grpc_slice_split_head(grpc_slice* source, size_t split) {
return grpc_slice_split_head_impl<true>(source, split);
}
grpc_slice grpc_slice_split_head_no_inline(grpc_slice* source, size_t split) {
return grpc_slice_split_head_impl<false>(source, split);
}
int grpc_slice_eq(grpc_slice a, grpc_slice b) {
if (GRPC_SLICE_LENGTH(a) != GRPC_SLICE_LENGTH(b)) return false;
if (GRPC_SLICE_LENGTH(a) == 0) return true;

@ -324,9 +324,13 @@ void grpc_slice_buffer_move_into(grpc_slice_buffer* src,
src->length = 0;
}
template <bool incref>
template <bool incref, bool allow_inline>
static void slice_buffer_move_first_maybe_ref(grpc_slice_buffer* src, size_t n,
grpc_slice_buffer* dst) {
if (n == 0) {
return;
}
GPR_ASSERT(src->length >= n);
if (src->length == n) {
grpc_slice_buffer_move_into(src, dst);
@ -346,14 +350,28 @@ static void slice_buffer_move_first_maybe_ref(grpc_slice_buffer* src, size_t n,
grpc_slice_buffer_add(dst, slice);
break;
} else if (incref) { // n < slice_len
grpc_slice_buffer_undo_take_first(
src, grpc_slice_split_tail_maybe_ref(&slice, n, GRPC_SLICE_REF_BOTH));
if (allow_inline) {
grpc_slice_buffer_undo_take_first(
src,
grpc_slice_split_tail_maybe_ref(&slice, n, GRPC_SLICE_REF_BOTH));
} else {
grpc_slice_buffer_undo_take_first(
src, grpc_slice_split_tail_maybe_ref_no_inline(
&slice, n, GRPC_SLICE_REF_BOTH));
}
GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == n);
grpc_slice_buffer_add(dst, slice);
break;
} else { // n < slice_len
grpc_slice_buffer_undo_take_first(
src, grpc_slice_split_tail_maybe_ref(&slice, n, GRPC_SLICE_REF_TAIL));
if (allow_inline) {
grpc_slice_buffer_undo_take_first(
src,
grpc_slice_split_tail_maybe_ref(&slice, n, GRPC_SLICE_REF_TAIL));
} else {
grpc_slice_buffer_undo_take_first(
src, grpc_slice_split_tail_maybe_ref_no_inline(
&slice, n, GRPC_SLICE_REF_TAIL));
}
GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == n);
grpc_slice_buffer_add_indexed(dst, slice);
break;
@ -364,14 +382,19 @@ static void slice_buffer_move_first_maybe_ref(grpc_slice_buffer* src, size_t n,
GPR_ASSERT(src->count > 0);
}
void grpc_slice_buffer_move_first_no_inline(grpc_slice_buffer* src, size_t n,
grpc_slice_buffer* dst) {
slice_buffer_move_first_maybe_ref<true, false>(src, n, dst);
}
void grpc_slice_buffer_move_first(grpc_slice_buffer* src, size_t n,
grpc_slice_buffer* dst) {
slice_buffer_move_first_maybe_ref<true>(src, n, dst);
slice_buffer_move_first_maybe_ref<true, true>(src, n, dst);
}
void grpc_slice_buffer_move_first_no_ref(grpc_slice_buffer* src, size_t n,
grpc_slice_buffer* dst) {
slice_buffer_move_first_maybe_ref<false>(src, n, dst);
slice_buffer_move_first_maybe_ref<false, true>(src, n, dst);
}
void grpc_slice_buffer_move_first_into_buffer(grpc_slice_buffer* src, size_t n,
@ -417,9 +440,9 @@ void grpc_slice_buffer_copy_first_into_buffer(grpc_slice_buffer* src, size_t n,
n -= slice_len;
}
}
void grpc_slice_buffer_trim_end(grpc_slice_buffer* sb, size_t n,
grpc_slice_buffer* garbage) {
template <bool allow_inline>
void grpc_slice_buffer_trim_end_impl(grpc_slice_buffer* sb, size_t n,
grpc_slice_buffer* garbage) {
GPR_ASSERT(n <= sb->length);
sb->length -= n;
for (;;) {
@ -427,7 +450,12 @@ void grpc_slice_buffer_trim_end(grpc_slice_buffer* sb, size_t n,
grpc_slice slice = sb->slices[idx];
size_t slice_len = GRPC_SLICE_LENGTH(slice);
if (slice_len > n) {
sb->slices[idx] = grpc_slice_split_head(&slice, slice_len - n);
if (allow_inline) {
sb->slices[idx] = grpc_slice_split_head(&slice, slice_len - n);
} else {
sb->slices[idx] =
grpc_slice_split_head_no_inline(&slice, slice_len - n);
}
if (garbage) {
grpc_slice_buffer_add_indexed(garbage, slice);
} else {
@ -454,6 +482,16 @@ void grpc_slice_buffer_trim_end(grpc_slice_buffer* sb, size_t n,
}
}
void grpc_slice_buffer_trim_end_no_inline(grpc_slice_buffer* sb, size_t n,
grpc_slice_buffer* garbage) {
return grpc_slice_buffer_trim_end_impl<false>(sb, n, garbage);
}
void grpc_slice_buffer_trim_end(grpc_slice_buffer* sb, size_t n,
grpc_slice_buffer* garbage) {
return grpc_slice_buffer_trim_end_impl<true>(sb, n, garbage);
}
grpc_slice grpc_slice_buffer_take_first(grpc_slice_buffer* sb) {
grpc_slice slice;
GPR_ASSERT(sb->count > 0);

@ -32,6 +32,12 @@
void grpc_slice_buffer_copy_first_into_buffer(grpc_slice_buffer* src, size_t n,
void* dst);
void grpc_slice_buffer_move_first_no_inline(grpc_slice_buffer* src, size_t n,
grpc_slice_buffer* dst);
void grpc_slice_buffer_trim_end_no_inline(grpc_slice_buffer* sb, size_t n,
grpc_slice_buffer* garbage);
namespace grpc_core {
/// A slice buffer holds the memory for a collection of slices.
@ -96,7 +102,14 @@ class SliceBuffer {
grpc_slice_buffer_trim_end(&slice_buffer_, n, nullptr);
}
/// Move the first n bytes of the SliceBuffer into a memory pointed to by dst.
/// Removes/deletes the last n bytes in the SliceBuffer while avoiding the
/// the creation of inline slices.
void RemoveLastNBytesNoInline(size_t n) {
grpc_slice_buffer_trim_end_no_inline(&slice_buffer_, n, nullptr);
}
/// Move the first n bytes of the SliceBuffer into a memory pointed to by
/// dst.
void MoveFirstNBytesIntoBuffer(size_t n, void* dst) {
grpc_slice_buffer_move_first_into_buffer(&slice_buffer_, n, dst);
}

@ -67,6 +67,13 @@ grpc_slice grpc_slice_from_cpp_string(std::string str);
// 0. All other slices will return the size of the allocated chars.
size_t grpc_slice_memory_usage(grpc_slice s);
grpc_slice grpc_slice_split_tail_maybe_ref_no_inline(
grpc_slice* source, size_t split, grpc_slice_ref_whom ref_whom);
grpc_slice grpc_slice_split_tail_no_inline(grpc_slice* source, size_t split);
grpc_slice grpc_slice_split_head_no_inline(grpc_slice* source, size_t split);
namespace grpc_core {
// Converts grpc_slice to absl::string_view.

@ -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>();
send_initial_metadata_->Set(HttpPathMetadata(), std::move(*args->path));
if (args->authority.has_value()) {
@ -3389,11 +3404,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());
@ -3408,7 +3428,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(),

@ -72,20 +72,13 @@ void RegisterSecurityFilters(CoreConfiguration::Builder* builder) {
builder->channel_init()
->RegisterFilter<ClientAuthFilter>(GRPC_CLIENT_DIRECT_CHANNEL)
.IfHasChannelArg(GRPC_ARG_SECURITY_CONNECTOR);
if (IsV3ServerAuthFilterEnabled()) {
builder->channel_init()
->RegisterFilter<ServerAuthFilter>(GRPC_SERVER_CHANNEL)
.IfHasChannelArg(GRPC_SERVER_CREDENTIALS_ARG);
} else {
builder->channel_init()
->RegisterFilter<LegacyServerAuthFilter>(GRPC_SERVER_CHANNEL)
.IfHasChannelArg(GRPC_SERVER_CREDENTIALS_ARG);
}
builder->channel_init()
->RegisterFilter<ServerAuthFilter>(GRPC_SERVER_CHANNEL)
.IfHasChannelArg(GRPC_SERVER_CREDENTIALS_ARG);
builder->channel_init()
->RegisterFilter<GrpcServerAuthzFilter>(GRPC_SERVER_CHANNEL)
.IfHasChannelArg(GRPC_ARG_AUTHORIZATION_POLICY_PROVIDER)
.After<ServerAuthFilter>()
.After<LegacyServerAuthFilter>();
.After<ServerAuthFilter>();
}
} // namespace grpc_core

@ -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));

@ -1330,13 +1330,10 @@ void Server::ChannelData::InitTransport(RefCountedPtr<Server> server,
++accept_stream_types;
op->set_accept_stream = true;
op->set_accept_stream_fn = AcceptStream;
if (IsRegisteredMethodLookupInTransportEnabled()) {
op->set_registered_method_matcher_fn = [](void* arg,
ClientMetadata* metadata) {
static_cast<ChannelData*>(arg)->SetRegisteredMethodOnMetadata(
*metadata);
};
}
op->set_registered_method_matcher_fn = [](void* arg,
ClientMetadata* metadata) {
static_cast<ChannelData*>(arg)->SetRegisteredMethodOnMetadata(*metadata);
};
op->set_accept_stream_user_data = this;
}
if (transport->server_transport() != nullptr) {
@ -1527,15 +1524,9 @@ ArenaPromise<ServerMetadataHandle> Server::ChannelData::MakeCallPromise(
}
// Find request matcher.
RequestMatcherInterface* matcher;
RegisteredMethod* rm = nullptr;
if (IsRegisteredMethodLookupInTransportEnabled()) {
rm = static_cast<RegisteredMethod*>(
call_args.client_initial_metadata->get(GrpcRegisteredMethod())
.value_or(nullptr));
} else {
rm = chand->GetRegisteredMethod(host_ptr->as_string_view(),
path_ptr->as_string_view());
}
RegisteredMethod* rm = static_cast<RegisteredMethod*>(
call_args.client_initial_metadata->get(GrpcRegisteredMethod())
.value_or(nullptr));
ArenaPromise<absl::StatusOr<NextResult<MessageHandle>>>
maybe_read_first_message([] { return NextResult<MessageHandle>(); });
if (rm != nullptr) {
@ -1760,7 +1751,6 @@ void Server::CallData::KillZombie() {
// If this changes, change MakeCallPromise too.
void Server::CallData::StartNewRpc(grpc_call_element* elem) {
auto* chand = static_cast<ChannelData*>(elem->channel_data);
if (server_->ShutdownCalled()) {
state_.store(CallState::ZOMBIED, std::memory_order_relaxed);
KillZombie();
@ -1771,15 +1761,8 @@ void Server::CallData::StartNewRpc(grpc_call_element* elem) {
grpc_server_register_method_payload_handling payload_handling =
GRPC_SRM_PAYLOAD_NONE;
if (path_.has_value() && host_.has_value()) {
RegisteredMethod* rm;
if (IsRegisteredMethodLookupInTransportEnabled()) {
rm = static_cast<RegisteredMethod*>(
recv_initial_metadata_->get(GrpcRegisteredMethod())
.value_or(nullptr));
} else {
rm = chand->GetRegisteredMethod(host_->as_string_view(),
path_->as_string_view());
}
RegisteredMethod* rm = static_cast<RegisteredMethod*>(
recv_initial_metadata_->get(GrpcRegisteredMethod()).value_or(nullptr));
if (rm != nullptr) {
matcher_ = rm->matcher.get();
payload_handling = rm->payload_handling;

@ -21,6 +21,7 @@
#include <stdint.h>
#include <atomic>
#include <cstring>
#include <functional>
#include <memory>
#include <utility>
@ -36,6 +37,8 @@
#include <grpc/slice_buffer.h>
#include <grpc/support/log.h>
#include "src/core/lib/event_engine/extensions/chaotic_good_extension.h"
#include "src/core/lib/event_engine/query_extensions.h"
#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/promise/activity.h"
@ -164,8 +167,9 @@ class PromiseEndpoint {
complete,
[this, num_bytes]() {
SliceBuffer ret;
grpc_slice_buffer_move_first(read_state_->buffer.c_slice_buffer(),
num_bytes, ret.c_slice_buffer());
grpc_slice_buffer_move_first_no_inline(
read_state_->buffer.c_slice_buffer(), num_bytes,
ret.c_slice_buffer());
return [ret = std::move(
ret)]() mutable -> Poll<absl::StatusOr<SliceBuffer>> {
return std::move(ret);
@ -180,8 +184,9 @@ class PromiseEndpoint {
// If read succeeds, return `SliceBuffer` with `num_bytes` bytes.
if (read_state->result.ok()) {
SliceBuffer ret;
grpc_slice_buffer_move_first(read_state->buffer.c_slice_buffer(),
num_bytes, ret.c_slice_buffer());
grpc_slice_buffer_move_first_no_inline(
read_state->buffer.c_slice_buffer(), num_bytes,
ret.c_slice_buffer());
read_state->complete.store(false, std::memory_order_relaxed);
return std::move(ret);
}
@ -214,6 +219,41 @@ class PromiseEndpoint {
});
}
// Enables RPC receive coalescing and alignment of memory holding received
// RPCs.
void EnforceRxMemoryAlignmentAndCoalescing() {
auto* chaotic_good_ext = grpc_event_engine::experimental::QueryExtension<
grpc_event_engine::experimental::ChaoticGoodExtension>(endpoint_.get());
if (chaotic_good_ext != nullptr) {
chaotic_good_ext->EnforceRxMemoryAlignment();
chaotic_good_ext->EnableRpcReceiveCoalescing();
if (read_state_->buffer.Length() == 0) {
return;
}
// Copy everything from read_state_->buffer into a single slice and
// replace the contents of read_state_->buffer with that slice.
grpc_slice slice = grpc_slice_malloc_large(read_state_->buffer.Length());
GPR_ASSERT(
reinterpret_cast<uintptr_t>(GRPC_SLICE_START_PTR(slice)) % 64 == 0);
size_t ofs = 0;
for (size_t i = 0; i < read_state_->buffer.Count(); i++) {
memcpy(
GRPC_SLICE_START_PTR(slice) + ofs,
GRPC_SLICE_START_PTR(
read_state_->buffer.c_slice_buffer()->slices[i]),
GRPC_SLICE_LENGTH(read_state_->buffer.c_slice_buffer()->slices[i]));
ofs +=
GRPC_SLICE_LENGTH(read_state_->buffer.c_slice_buffer()->slices[i]);
}
read_state_->buffer.Clear();
read_state_->buffer.AppendIndexed(
grpc_event_engine::experimental::Slice(slice));
GPR_DEBUG_ASSERT(read_state_->buffer.Length() == ofs);
}
}
const grpc_event_engine::experimental::EventEngine::ResolvedAddress&
GetPeerAddress() const;
const grpc_event_engine::experimental::EventEngine::ResolvedAddress&

@ -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(

@ -15,18 +15,10 @@
//
//
#include <utility>
#include "absl/status/status.h"
#include <grpc/grpc.h>
#include <grpcpp/support/client_callback.h>
#include <grpcpp/support/status.h>
#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/iomgr/executor.h"
#include "src/core/lib/surface/call.h"
namespace grpc {

@ -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",
],

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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
//
@ -98,15 +150,19 @@ OpenTelemetryPluginBuilderImpl::SetMeterProvider(
return *this;
}
OpenTelemetryPluginBuilderImpl& OpenTelemetryPluginBuilderImpl::EnableMetric(
absl::string_view metric_name) {
metrics_.emplace(metric_name);
OpenTelemetryPluginBuilderImpl& OpenTelemetryPluginBuilderImpl::EnableMetrics(
absl::Span<const absl::string_view> metric_names) {
for (const auto& metric_name : metric_names) {
metrics_.emplace(metric_name);
}
return *this;
}
OpenTelemetryPluginBuilderImpl& OpenTelemetryPluginBuilderImpl::DisableMetric(
absl::string_view metric_name) {
metrics_.erase(metric_name);
OpenTelemetryPluginBuilderImpl& OpenTelemetryPluginBuilderImpl::DisableMetrics(
absl::Span<const absl::string_view> metric_names) {
for (const auto& metric_name : metric_names) {
metrics_.erase(metric_name);
}
return *this;
}
@ -156,112 +212,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
@ -315,6 +611,23 @@ OpenTelemetryPluginBuilder::SetGenericMethodAttributeFilter(
return *this;
}
OpenTelemetryPluginBuilder& OpenTelemetryPluginBuilder::EnableMetrics(
absl::Span<const absl::string_view> metric_names) {
impl_->EnableMetrics(metric_names);
return *this;
}
OpenTelemetryPluginBuilder& OpenTelemetryPluginBuilder::DisableMetrics(
absl::Span<const absl::string_view> metric_names) {
impl_->DisableMetrics(metric_names);
return *this;
}
OpenTelemetryPluginBuilder& OpenTelemetryPluginBuilder::DisableAllMetrics() {
impl_->DisableAllMetrics();
return *this;
}
OpenTelemetryPluginBuilder& OpenTelemetryPluginBuilder::AddPluginOption(
std::unique_ptr<OpenTelemetryPluginOption> option) {
impl_->AddPluginOption(
@ -324,6 +637,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();
}

@ -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();
@ -169,8 +135,10 @@ class OpenTelemetryPluginBuilderImpl {
// grpc.server.call.duration
// grpc.server.call.sent_total_compressed_message_size
// grpc.server.call.rcvd_total_compressed_message_size
OpenTelemetryPluginBuilderImpl& EnableMetric(absl::string_view metric_name);
OpenTelemetryPluginBuilderImpl& DisableMetric(absl::string_view metric_name);
OpenTelemetryPluginBuilderImpl& EnableMetrics(
absl::Span<const absl::string_view> metric_names);
OpenTelemetryPluginBuilderImpl& DisableMetrics(
absl::Span<const absl::string_view> metric_names);
OpenTelemetryPluginBuilderImpl& DisableAllMetrics();
// If set, \a target_selector is called per channel to decide whether to
// collect metrics on that target or not.
@ -202,8 +170,15 @@ 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();
const absl::flat_hash_set<std::string>& TestOnlyEnabledMetrics() {
return metrics_;
}
private:
std::shared_ptr<opentelemetry::metrics::MeterProvider> meter_provider_;
std::unique_ptr<LabelsInjector> labels_injector_;
@ -217,53 +192,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);
});
}
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);
static ActivePluginOptionsView MakeForServer(
const grpc_core::ChannelArgs& args) {
return ActivePluginOptionsView(
[&args](const InternalOpenTelemetryPluginOption& plugin_option) {
return plugin_option.IsActiveOnServer(args);
});
}
private:
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 {
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;
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;
}
return true;
}
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);
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

@ -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

@ -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 {
// OpenTelemetryPlugin::ServerCallTracer implementation
class OpenTelemetryPlugin::ServerCallTracer
: public grpc_core::ServerCallTracer {
public:
grpc_core::ServerCallTracer* CreateNewServerCallTracer(
grpc_core::Arena* arena,
const grpc_core::ChannelArgs& channel_args) override;
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";
}
bool IsServerTraced(const grpc_core::ChannelArgs& args) override;
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

@ -15,72 +15,29 @@
//
//
#include "absl/status/status.h"
#include <grpcpp/support/server_callback.h>
#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/iomgr/executor.h"
namespace grpc {
namespace internal {
void ServerCallbackCall::ScheduleOnDone(bool inline_ondone) {
if (inline_ondone) {
CallOnDone();
} else {
// Unlike other uses of closure, do not Ref or Unref here since at this
// point, all the Ref'fing and Unref'fing is done for this call.
grpc_core::ExecCtx exec_ctx;
struct ClosureWithArg {
grpc_closure closure;
ServerCallbackCall* call;
explicit ClosureWithArg(ServerCallbackCall* call_arg) : call(call_arg) {
GRPC_CLOSURE_INIT(
&closure,
[](void* void_arg, grpc_error_handle) {
ClosureWithArg* arg = static_cast<ClosureWithArg*>(void_arg);
arg->call->CallOnDone();
delete arg;
},
this, grpc_schedule_on_exec_ctx);
}
};
ClosureWithArg* arg = new ClosureWithArg(this);
grpc_core::Executor::Run(&arg->closure, absl::OkStatus());
return;
}
RunAsync([this]() { CallOnDone(); });
}
void ServerCallbackCall::CallOnCancel(ServerReactor* reactor) {
if (reactor->InternalInlineable()) {
reactor->OnCancel();
} else {
// Ref to make sure that the closure executes before the whole call gets
// destructed, and Unref within the closure.
Ref();
grpc_core::ExecCtx exec_ctx;
struct ClosureWithArg {
grpc_closure closure;
ServerCallbackCall* call;
ServerReactor* reactor;
ClosureWithArg(ServerCallbackCall* call_arg, ServerReactor* reactor_arg)
: call(call_arg), reactor(reactor_arg) {
GRPC_CLOSURE_INIT(
&closure,
[](void* void_arg, grpc_error_handle) {
ClosureWithArg* arg = static_cast<ClosureWithArg*>(void_arg);
arg->reactor->OnCancel();
arg->call->MaybeDone();
delete arg;
},
this, grpc_schedule_on_exec_ctx);
}
};
ClosureWithArg* arg = new ClosureWithArg(this, reactor);
grpc_core::Executor::Run(&arg->closure, absl::OkStatus());
return;
}
Ref();
RunAsync([this, reactor]() {
reactor->OnCancel();
MaybeDone();
});
}
} // namespace internal

@ -14,8 +14,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
load("//bazel:grpc_build_system.bzl", "grpc_generate_objc_one_off_targets", "grpc_objc_library")
load("@build_bazel_rules_apple//apple:resources.bzl", "apple_resource_bundle")
load("//bazel:grpc_build_system.bzl", "grpc_generate_objc_one_off_targets", "grpc_objc_library")
licenses(["notice"])

@ -696,12 +696,12 @@ Pod::Spec.new do |s|
# PrivacyInfo.xcprivacy is not part of BoringSSL repo, inject it during pod installation
base64 --decode $opts <<EOF | gunzip > src/PrivacyInfo.xcprivacy
H4sICAAAAAAC/1ByaXZhY3lJbmZvLnhjcHJpdmFjeQC1kl9PwjAUxZ/Hp6h9Z1di/JsxAhskJAQXGQ8+
Nt0VG7a1aRuw395OHUhE8UHflrNzzj2/pNHgpSrJBrURsu7TXnhOCdZcFqJe9ekyn3Rv6CDuRGfpfZI/
ZmOiSmEsyZaj2TQhtAswVKpEgDRPSTabLnLiOwDGc0ros7XqDmC73YascYVcVo3RQKalQm3dzJd1fSAs
bEH9mff2gzleLQS3cSeI1uji+SLTYsO4yzXja78ygkb2f59YaRC++BJZlsgtFimzLHcKzS7BtGYOvm1O
ZcVEfdI+5ByNwWKYTY/U+4+gBQh+TrZBbzNW+wFHnQmzuJLaTUSJuajQWFapCD4SJ488IDNyDxV8mrm/
m1z1rsPeYSnscaDl+RewhTMWq5GUtsH7Y7KLy8ntL8h2WqtE8PY0484rAb5xoDEDAAA=
H4sICAAAAAAC/1ByaXZhY3lJbmZvLnhjcHJpdmFjeQCFUU1PwjAYPo9fUXtnr7uoMWMEN0iWEFykHDw2
3Ss2dGvTNuD+vUWdk4hya54+n3nT6VujyB6tk7qd0CS+pgRboWvZbid0wxbjOzrNRulV8Ziz52pOjJLO
k2rzsCxzQscAM2MUAhSsINWyXDMSPADmK0roq/fmHuBwOMT8yIqFbo5EB5XVBq3vlsFsHARx7WsaYj7d
T+oEtJbCZ6Mo3WGXrdaVlXsuOma52IWWKRzh8PvClUP4xcu1Uig81gX3nHUG3beCW8s7+NO50A2X7UX6
TAh0DutZVZ6xD4+oHxD9r+yFgea8DQXOMnPucattt5AKmWzQed6YFL4UF0OekDs9jIp+1Bxy85vkNk5O
TWGYA/1BeqxHUvg4YDZ6B1ry6jZXAgAA
EOF
# We are renaming openssl to openssl_grpc so that there is no conflict with openssl if it exists

@ -18,14 +18,6 @@
<string>C617.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>35F9.1</string>
</array>
</dict>
</array>
</dict>
</plist>

@ -14,15 +14,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.
load("@build_bazel_rules_apple//apple:ios.bzl", "ios_application")
load("@build_bazel_rules_apple//apple:tvos.bzl", "tvos_application")
load("@build_bazel_rules_apple//apple:watchos.bzl", "watchos_application", "watchos_extension")
load(
"//src/objective-c:grpc_objc_internal_library.bzl",
"grpc_objc_examples_library",
"local_objc_grpc_library",
"proto_library_objc_wrapper",
)
load("@build_bazel_rules_apple//apple:ios.bzl", "ios_application")
load("@build_bazel_rules_apple//apple:tvos.bzl", "tvos_application")
load("@build_bazel_rules_apple//apple:watchos.bzl", "watchos_application", "watchos_extension")
licenses(["notice"])

@ -23,6 +23,11 @@ Each rule listed must be re-written for Google's internal build system, and
each change must be ported from one to the other.
"""
load("@build_bazel_rules_apple//apple:ios.bzl", "ios_unit_test")
load(
"@build_bazel_rules_apple//apple/testing/default_runner:ios_test_runner.bzl",
"ios_test_runner",
)
load("@rules_proto//proto:defs.bzl", "proto_library")
load(
"//bazel:generate_objc.bzl",
@ -32,11 +37,6 @@ load(
"generate_objc_srcs",
)
load("//bazel:grpc_build_system.bzl", "grpc_objc_library")
load("@build_bazel_rules_apple//apple:ios.bzl", "ios_unit_test")
load(
"@build_bazel_rules_apple//apple/testing/default_runner:ios_test_runner.bzl",
"ios_test_runner",
)
# The default device type for ios objc unit tests
IOS_UNIT_TEST_DEVICE_TYPE = "iPhone 11"

@ -14,6 +14,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
load("@build_bazel_rules_apple//apple:macos.bzl", "macos_unit_test")
load("@build_bazel_rules_apple//apple:resources.bzl", "apple_resource_bundle")
load("@build_bazel_rules_apple//apple:tvos.bzl", "tvos_application", "tvos_unit_test")
load("//bazel:grpc_build_system.bzl", "grpc_sh_test")
load(
"//src/objective-c:grpc_objc_internal_library.bzl",
@ -22,9 +25,6 @@ load(
"local_objc_grpc_library",
"proto_library_objc_wrapper",
)
load("@build_bazel_rules_apple//apple:resources.bzl", "apple_resource_bundle")
load("@build_bazel_rules_apple//apple:macos.bzl", "macos_unit_test")
load("@build_bazel_rules_apple//apple:tvos.bzl", "tvos_application", "tvos_unit_test")
licenses(["notice"])

@ -12,9 +12,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
load("//bazel:python_rules.bzl", "py_grpc_library", "py_proto_library")
load("@rules_proto//proto:defs.bzl", "proto_library")
load("//bazel:grpc_build_system.bzl", "grpc_package", "grpc_proto_library")
load("//bazel:python_rules.bzl", "py_grpc_library", "py_proto_library")
licenses(["notice"])

@ -12,8 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
load("//bazel:python_rules.bzl", "py_grpc_library", "py_proto_library")
load("//bazel:grpc_build_system.bzl", "grpc_package", "grpc_proto_library")
load("//bazel:python_rules.bzl", "py_grpc_library", "py_proto_library")
licenses(["notice"])

@ -45,7 +45,6 @@ CORE_SOURCE_FILES = [
'src/core/ext/filters/http/client_authority_filter.cc',
'src/core/ext/filters/http/http_filters_plugin.cc',
'src/core/ext/filters/http/message_compress/compression_filter.cc',
'src/core/ext/filters/http/message_compress/legacy_compression_filter.cc',
'src/core/ext/filters/http/server/http_server_filter.cc',
'src/core/ext/filters/message_size/message_size_filter.cc',
'src/core/ext/filters/rbac/rbac_filter.cc',
@ -724,13 +723,11 @@ CORE_SOURCE_FILES = [
'src/core/lib/security/security_connector/ssl_utils.cc',
'src/core/lib/security/security_connector/tls/tls_security_connector.cc',
'src/core/lib/security/transport/client_auth_filter.cc',
'src/core/lib/security/transport/legacy_server_auth_filter.cc',
'src/core/lib/security/transport/secure_endpoint.cc',
'src/core/lib/security/transport/security_handshaker.cc',
'src/core/lib/security/transport/server_auth_filter.cc',
'src/core/lib/security/transport/tsi_error.cc',
'src/core/lib/security/util/json_util.cc',
'src/core/lib/slice/b64.cc',
'src/core/lib/slice/percent_encoding.cc',
'src/core/lib/slice/slice.cc',
'src/core/lib/slice/slice_buffer.cc',

@ -1,3 +1,5 @@
load("@com_github_grpc_grpc//bazel:python_rules.bzl", "py_grpc_library", "py_proto_library")
# Copyright 2021 The gRPC Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
@ -12,7 +14,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
load("@rules_proto//proto:defs.bzl", "proto_library")
load("@com_github_grpc_grpc//bazel:python_rules.bzl", "py_grpc_library", "py_proto_library")
proto_library(
name = "unary_stream_benchmark_proto",

@ -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"};

@ -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"};

@ -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",

@ -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;

@ -12,8 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_package")
load("//bazel:custom_exec_properties.bzl", "LARGE_MACHINE")
load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_package")
load("//test/core/util:grpc_fuzzer.bzl", "grpc_proto_fuzzer")
licenses(["notice"])

@ -12,8 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package")
load("//bazel:custom_exec_properties.bzl", "LARGE_MACHINE")
load("//bazel:grpc_build_system.bzl", "grpc_cc_library", "grpc_cc_test", "grpc_package")
licenses(["notice"])

@ -149,7 +149,7 @@ static bool test_identity(const grpc_auth_context* ctx,
return false;
}
if (strncmp(prop->value, expected_identity, prop->value_length) != 0) {
gpr_log(GPR_ERROR, "Expected peer identity %s and got got %s.",
gpr_log(GPR_ERROR, "Expected peer identity %s and got %s.",
expected_identity, prop->value);
return false;
}

@ -19,28 +19,6 @@ grpc_package(name = "test/core/slice")
licenses(["notice"])
grpc_fuzzer(
name = "b64_encode_fuzzer",
srcs = ["b64_encode_fuzzer.cc"],
corpus = "b64_encode_corpus",
language = "C++",
tags = ["no_windows"],
deps = [
"//:grpc",
],
)
grpc_fuzzer(
name = "b64_decode_fuzzer",
srcs = ["b64_decode_fuzzer.cc"],
corpus = "b64_decode_corpus",
language = "C++",
tags = ["no_windows"],
deps = [
"//:grpc",
],
)
grpc_fuzzer(
name = "percent_encode_fuzzer",
srcs = ["percent_encode_fuzzer.cc"],
@ -138,18 +116,3 @@ grpc_cc_test(
"//test/core/util:grpc_test_util",
],
)
grpc_cc_test(
name = "b64_test",
srcs = ["b64_test.cc"],
external_deps = ["gtest"],
language = "C++",
uses_event_engine = False,
uses_polling = False,
deps = [
"//:gpr",
"//:grpc",
"//src/core:slice",
"//test/core/util:grpc_test_util",
],
)

@ -1,39 +0,0 @@
//
//
// Copyright 2019 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 <stddef.h>
#include <stdint.h>
#include <grpc/grpc.h>
#include <grpc/slice.h>
#include "src/core/lib/slice/b64.h"
bool squelch = true;
bool leak_check = true;
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
if (size < 1) return 0;
grpc_init();
const bool url_safe = static_cast<uint8_t>(0x100) < data[0];
grpc_slice res = grpc_base64_decode_with_len(
reinterpret_cast<const char*>(data + 1), size - 1, url_safe);
grpc_slice_unref(res);
grpc_shutdown();
return 0;
}

@ -1,37 +0,0 @@
//
//
// Copyright 2019 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 <stddef.h>
#include <stdint.h>
#include <grpc/support/alloc.h>
#include "src/core/lib/slice/b64.h"
bool squelch = true;
bool leak_check = true;
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
if (size < 2) return 0;
const bool url_safe = static_cast<uint8_t>(0x100) < data[0];
const bool multiline = static_cast<uint8_t>(0x100) < data[1];
char* res = grpc_base64_encode(reinterpret_cast<const char*>(data + 2),
size - 2, url_safe, multiline);
gpr_free(res);
return 0;
}

@ -1,193 +0,0 @@
//
//
// Copyright 2015 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//
#include "src/core/lib/slice/b64.h"
#include <stdint.h>
#include <string.h>
#include <memory>
#include "absl/strings/string_view.h"
#include "gtest/gtest.h"
#include <grpc/slice.h>
#include <grpc/support/alloc.h>
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/slice/slice_internal.h"
#include "test/core/util/test_config.h"
static void test_simple_encode_decode_b64(int url_safe, int multiline) {
const char* hello = "hello";
char* hello_b64 =
grpc_base64_encode(hello, strlen(hello), url_safe, multiline);
grpc_core::ExecCtx exec_ctx;
grpc_slice hello_slice = grpc_base64_decode(hello_b64, url_safe);
ASSERT_EQ(grpc_core::StringViewFromSlice(hello_slice),
absl::string_view(hello));
grpc_slice_unref(hello_slice);
gpr_free(hello_b64);
}
static void test_full_range_encode_decode_b64(int url_safe, int multiline) {
unsigned char orig[256];
size_t i;
char* b64;
grpc_slice orig_decoded;
for (i = 0; i < sizeof(orig); i++) orig[i] = static_cast<uint8_t>(i);
// Try all the different paddings.
for (i = 0; i < 3; i++) {
grpc_core::ExecCtx exec_ctx;
b64 = grpc_base64_encode(orig, sizeof(orig) - i, url_safe, multiline);
orig_decoded = grpc_base64_decode(b64, url_safe);
ASSERT_EQ(
grpc_core::StringViewFromSlice(orig_decoded),
absl::string_view(reinterpret_cast<char*>(orig), sizeof(orig) - i));
grpc_slice_unref(orig_decoded);
gpr_free(b64);
}
}
TEST(B64Test, SimpleEncodeDecodeB64NoMultiline) {
test_simple_encode_decode_b64(0, 0);
}
TEST(B64Test, SimpleEncodeDecodeB64Multiline) {
test_simple_encode_decode_b64(0, 1);
}
TEST(B64Test, SimpleEncodeDecodeB64UrlsafeNoMultiline) {
test_simple_encode_decode_b64(1, 0);
}
TEST(B64Test, SimpleEncodeDecodeB64UrlsafeMultiline) {
test_simple_encode_decode_b64(1, 1);
}
TEST(B64Test, FullRangeEncodeDecodeB64NoMultiline) {
test_full_range_encode_decode_b64(0, 0);
}
TEST(B64Test, FullRangeEncodeDecodeB64Multiline) {
test_full_range_encode_decode_b64(0, 1);
}
TEST(B64Test, FullRangeEncodeDecodeB64UrlsafeNoMultiline) {
test_full_range_encode_decode_b64(1, 0);
}
TEST(B64Test, FullRangeEncodeDecodeB64UrlsafeMultiline) {
test_full_range_encode_decode_b64(1, 1);
}
TEST(B64Test, UrlSafeUnsafeMismatchFailure) {
unsigned char orig[256];
size_t i;
char* b64;
grpc_slice orig_decoded;
int url_safe = 1;
for (i = 0; i < sizeof(orig); i++) orig[i] = static_cast<uint8_t>(i);
grpc_core::ExecCtx exec_ctx;
b64 = grpc_base64_encode(orig, sizeof(orig), url_safe, 0);
orig_decoded = grpc_base64_decode(b64, !url_safe);
ASSERT_TRUE(GRPC_SLICE_IS_EMPTY(orig_decoded));
gpr_free(b64);
grpc_slice_unref(orig_decoded);
b64 = grpc_base64_encode(orig, sizeof(orig), !url_safe, 0);
orig_decoded = grpc_base64_decode(b64, url_safe);
ASSERT_TRUE(GRPC_SLICE_IS_EMPTY(orig_decoded));
gpr_free(b64);
grpc_slice_unref(orig_decoded);
}
TEST(B64Test, Rfc4648TestVectors) {
char* b64;
b64 = grpc_base64_encode("", 0, 0, 0);
ASSERT_STREQ("", b64);
gpr_free(b64);
b64 = grpc_base64_encode("f", 1, 0, 0);
ASSERT_STREQ("Zg==", b64);
gpr_free(b64);
b64 = grpc_base64_encode("fo", 2, 0, 0);
ASSERT_STREQ("Zm8=", b64);
gpr_free(b64);
b64 = grpc_base64_encode("foo", 3, 0, 0);
ASSERT_STREQ("Zm9v", b64);
gpr_free(b64);
b64 = grpc_base64_encode("foob", 4, 0, 0);
ASSERT_STREQ("Zm9vYg==", b64);
gpr_free(b64);
b64 = grpc_base64_encode("fooba", 5, 0, 0);
ASSERT_STREQ("Zm9vYmE=", b64);
gpr_free(b64);
b64 = grpc_base64_encode("foobar", 6, 0, 0);
ASSERT_STREQ("Zm9vYmFy", b64);
gpr_free(b64);
}
TEST(B64Test, UnpaddedDecode) {
grpc_slice decoded;
grpc_core::ExecCtx exec_ctx;
decoded = grpc_base64_decode("Zm9vYmFy", 0);
ASSERT_EQ(grpc_core::StringViewFromSlice(decoded), "foobar");
grpc_slice_unref(decoded);
decoded = grpc_base64_decode("Zm9vYmE", 0);
ASSERT_EQ(grpc_core::StringViewFromSlice(decoded), "fooba");
grpc_slice_unref(decoded);
decoded = grpc_base64_decode("Zm9vYg", 0);
ASSERT_EQ(grpc_core::StringViewFromSlice(decoded), "foob");
grpc_slice_unref(decoded);
decoded = grpc_base64_decode("Zm9v", 0);
ASSERT_EQ(grpc_core::StringViewFromSlice(decoded), "foo");
grpc_slice_unref(decoded);
decoded = grpc_base64_decode("Zm8", 0);
ASSERT_EQ(grpc_core::StringViewFromSlice(decoded), "fo");
grpc_slice_unref(decoded);
decoded = grpc_base64_decode("Zg", 0);
ASSERT_EQ(grpc_core::StringViewFromSlice(decoded), "f");
grpc_slice_unref(decoded);
decoded = grpc_base64_decode("", 0);
ASSERT_TRUE(GRPC_SLICE_IS_EMPTY(decoded));
}
int main(int argc, char** argv) {
grpc::testing::TestEnvironment env(&argc, argv);
::testing::InitGoogleTest(&argc, argv);
grpc::testing::TestGrpcScope grpc_scope;
return RUN_ALL_TESTS();
}

@ -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"

@ -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"

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save