Merge branch 'master' into transport-refs-2

pull/36598/head
Craig Tiller 11 months ago
commit bc95fbcea5
  1. 76
      BUILD
  2. 45
      CMakeLists.txt
  3. 2
      Makefile
  4. 4
      Package.swift
  5. 29
      bazel/experiments.bzl
  6. 30
      build_autogenerated.yaml
  7. 1
      config.m4
  8. 1
      config.w32
  9. 5
      gRPC-C++.podspec
  10. 6
      gRPC-Core.podspec
  11. 4
      grpc.gemspec
  12. 1
      include/grpc/module.modulemap
  13. 62
      include/grpc/passive_listener.h
  14. 6
      include/grpc/support/log.h
  15. 27
      include/grpcpp/passive_listener.h
  16. 1
      include/grpcpp/security/server_credentials.h
  17. 5
      include/grpcpp/security/tls_credentials_options.h
  18. 28
      include/grpcpp/server_builder.h
  19. 4
      package.xml
  20. 162
      src/core/BUILD
  21. 4
      src/core/ext/filters/logging/logging_filter.cc
  22. 7
      src/core/ext/transport/binder/server/binder_server.cc
  23. 29
      src/core/ext/transport/binder/transport/binder_transport.cc
  24. 21
      src/core/ext/transport/binder/wire_format/wire_reader_impl.cc
  25. 7
      src/core/ext/transport/chaotic_good/server/chaotic_good_server.cc
  26. 4
      src/core/ext/transport/chaotic_good/server/chaotic_good_server.h
  27. 76
      src/core/ext/transport/chaotic_good/server_transport.cc
  28. 12
      src/core/ext/transport/chaotic_good/server_transport.h
  29. 296
      src/core/ext/transport/chttp2/server/chttp2_server.cc
  30. 33
      src/core/ext/transport/chttp2/server/chttp2_server.h
  31. 3
      src/core/ext/transport/chttp2/transport/chttp2_transport.cc
  32. 1
      src/core/ext/transport/cronet/BUILD
  33. 51
      src/core/ext/transport/inproc/inproc_transport.cc
  34. 2
      src/core/ext/transport/inproc/inproc_transport.h
  35. 26
      src/core/lib/channel/channel_stack.cc
  36. 1
      src/core/lib/channel/channel_stack.h
  37. 193
      src/core/lib/channel/metrics.cc
  38. 308
      src/core/lib/channel/metrics.h
  39. 7
      src/core/lib/event_engine/extensions/supports_fd.h
  40. 16
      src/core/lib/event_engine/posix_engine/posix_engine.cc
  41. 2
      src/core/lib/event_engine/posix_engine/posix_engine.h
  42. 20
      src/core/lib/event_engine/thread_pool/work_stealing_thread_pool.cc
  43. 9
      src/core/lib/event_engine/thread_pool/work_stealing_thread_pool.h
  44. 50
      src/core/lib/experiments/experiments.cc
  45. 11
      src/core/lib/experiments/experiments.h
  46. 11
      src/core/lib/experiments/experiments.yaml
  47. 6
      src/core/lib/experiments/rollouts.yaml
  48. 19
      src/core/lib/gpr/android/log.cc
  49. 45
      src/core/lib/gpr/linux/log.cc
  50. 11
      src/core/lib/gpr/log.cc
  51. 42
      src/core/lib/gpr/posix/log.cc
  52. 43
      src/core/lib/gpr/windows/log.cc
  53. 54
      src/core/lib/gprpp/dump_args.cc
  54. 69
      src/core/lib/gprpp/dump_args.h
  55. 25
      src/core/lib/iomgr/ev_epoll1_linux.cc
  56. 27
      src/core/lib/iomgr/tcp_posix.cc
  57. 11
      src/core/lib/promise/detail/promise_like.h
  58. 711
      src/core/lib/promise/detail/seq_state.h
  59. 2
      src/core/lib/promise/status_flag.h
  60. 58
      src/core/lib/security/credentials/jwt/jwt_verifier.cc
  61. 1019
      src/core/lib/surface/call.cc
  62. 60
      src/core/lib/surface/call.h
  63. 84
      src/core/lib/surface/channel_init.cc
  64. 116
      src/core/lib/surface/channel_init.h
  65. 4
      src/core/lib/surface/init.cc
  66. 18
      src/core/lib/transport/call_destination.h
  67. 44
      src/core/lib/transport/call_filters.h
  68. 8
      src/core/lib/transport/call_spine.h
  69. 11
      src/core/lib/transport/interception_chain.h
  70. 67
      src/core/lib/transport/transport.h
  71. 12
      src/core/load_balancing/pick_first/pick_first.cc
  72. 49
      src/core/load_balancing/rls/rls.cc
  73. 31
      src/core/load_balancing/weighted_round_robin/weighted_round_robin.cc
  74. 7
      src/core/load_balancing/xds/xds_override_host.cc
  75. 3
      src/core/plugin_registry/grpc_plugin_registry.cc
  76. 632
      src/core/server/server.cc
  77. 47
      src/core/server/server.h
  78. 2
      src/core/server/server_interface.h
  79. 65
      src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc
  80. 34
      src/core/xds/grpc/xds_client_grpc.cc
  81. 1
      src/cpp/ext/csm/BUILD
  82. 2
      src/cpp/ext/gcp/BUILD
  83. 251
      src/cpp/ext/otel/otel_plugin.cc
  84. 20
      src/cpp/ext/otel/otel_plugin.h
  85. 60
      src/cpp/server/server_builder.cc
  86. 1
      src/python/grpcio/grpc_core_dependencies.py
  87. 28
      templates/tools/dockerfile/test/cxx_gcc_7_x64/Dockerfile.template
  88. 6
      test/core/address_utils/BUILD
  89. 14
      test/core/address_utils/parse_address_test.cc
  90. 13
      test/core/address_utils/parse_address_with_named_scope_id_test.cc
  91. 15
      test/core/bad_client/bad_client.cc
  92. 7
      test/core/bad_client/generate_tests.bzl
  93. 5
      test/core/bad_connection/BUILD
  94. 14
      test/core/bad_connection/close_fd_test.cc
  95. 1
      test/core/bad_ssl/generate_tests.bzl
  96. 4
      test/core/bad_ssl/server_common.cc
  97. 2
      test/core/channel/BUILD
  98. 6
      test/core/channel/channel_args_test.cc
  99. 547
      test/core/channel/metrics_test.cc
  100. 10
      test/core/compression/BUILD
  101. Some files were not shown because too many files have changed in this diff Show More

76
BUILD

@ -296,6 +296,7 @@ GRPC_PUBLIC_HDRS = [
"include/grpc/grpc_posix.h",
"include/grpc/grpc_security.h",
"include/grpc/grpc_security_constants.h",
"include/grpc/passive_listener.h",
"include/grpc/slice.h",
"include/grpc/slice_buffer.h",
"include/grpc/status.h",
@ -457,6 +458,7 @@ GRPCXX_PUBLIC_HDRS = [
"include/grpcpp/impl/service_type.h",
"include/grpcpp/impl/status.h",
"include/grpcpp/impl/sync.h",
"include/grpcpp/passive_listener.h",
"include/grpcpp/resource_quota.h",
"include/grpcpp/security/audit_logging.h",
"include/grpcpp/security/tls_crl_provider.h",
@ -581,6 +583,7 @@ grpc_cc_library(
defines = ["GRPC_NO_XDS"],
external_deps = [
"absl/base:core_headers",
"absl/log:log",
],
language = "c++",
public_hdrs = GRPC_PUBLIC_HDRS,
@ -652,6 +655,7 @@ grpc_cc_library(
}),
external_deps = [
"absl/base:core_headers",
"absl/log:log",
],
language = "c++",
public_hdrs = GRPC_PUBLIC_HDRS,
@ -785,9 +789,9 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/base:log_severity",
"absl/functional:any_invocable",
"absl/log",
"absl/log:check",
"absl/log:globals",
"absl/log:log",
"absl/memory",
"absl/random",
"absl/status",
@ -883,7 +887,7 @@ grpc_cc_library(
grpc_cc_library(
name = "grpc_public_hdrs",
hdrs = GRPC_PUBLIC_HDRS,
hdrs = GRPC_PUBLIC_HDRS + GRPC_PUBLIC_EVENT_ENGINE_HDRS,
external_deps = [
"absl/status:statusor",
"absl/strings",
@ -904,6 +908,7 @@ grpc_cc_library(
hdrs = GRPCXX_PUBLIC_HDRS,
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings:cord",
"absl/synchronization",
"protobuf_headers",
@ -934,6 +939,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings:cord",
],
language = "c++",
@ -1003,6 +1009,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -1062,6 +1069,7 @@ grpc_cc_library(
],
external_deps = [
"absl/container:flat_hash_set",
"absl/log:log",
"absl/strings",
"absl/types:optional",
"absl/types:span",
@ -1134,6 +1142,7 @@ grpc_cc_library(
"absl/functional:any_invocable",
"absl/hash",
"absl/log:check",
"absl/log:log",
"absl/memory",
"absl/meta:type_traits",
"absl/status",
@ -1247,6 +1256,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings",
"absl/synchronization",
],
@ -1379,6 +1389,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/status:statusor",
"absl/strings",
"absl/types:optional",
@ -1438,6 +1449,7 @@ grpc_cc_library(
external_deps = [
"absl/container:inlined_vector",
"absl/log:check",
"absl/log:log",
],
language = "c++",
deps = [
@ -1489,6 +1501,9 @@ grpc_cc_library(
hdrs = [
"//src/core:lib/surface/api_trace.h",
],
external_deps = [
"absl/log:log",
],
language = "c++",
deps = [
"gpr",
@ -1643,6 +1658,7 @@ grpc_cc_library(
"absl/container:flat_hash_set",
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -1806,6 +1822,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/types:optional",
@ -1895,6 +1912,7 @@ grpc_cc_library(
"absl/container:flat_hash_set",
"absl/hash",
"absl/log:check",
"absl/log:log",
"absl/random",
"absl/status",
"absl/status:statusor",
@ -1924,9 +1942,7 @@ grpc_cc_library(
"promise",
"ref_counted_ptr",
"stats",
"//src/core:1999",
"//src/core:activity",
"//src/core:arena",
"//src/core:arena_promise",
"//src/core:cancel_callback",
"//src/core:channel_args",
@ -1940,6 +1956,7 @@ grpc_cc_library(
"//src/core:error",
"//src/core:error_utils",
"//src/core:experiments",
"//src/core:interception_chain",
"//src/core:iomgr_fwd",
"//src/core:map",
"//src/core:metadata_batch",
@ -2013,6 +2030,7 @@ grpc_cc_library(
"absl/functional:any_invocable",
"absl/functional:function_ref",
"absl/log:check",
"absl/log:log",
"absl/meta:type_traits",
"absl/status",
"absl/status:statusor",
@ -2059,6 +2077,7 @@ grpc_cc_library(
"//src/core:arena_promise",
"//src/core:atomic_utils",
"//src/core:bitset",
"//src/core:call_destination",
"//src/core:call_filters",
"//src/core:call_final_info",
"//src/core:call_finalization",
@ -2287,6 +2306,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/container:inlined_vector",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -2394,6 +2414,7 @@ grpc_cc_library(
"//src/core:tsi/alts/handshaker/transport_security_common_api.h",
],
external_deps = [
"absl/log:log",
"@com_google_protobuf//upb:base",
"@com_google_protobuf//upb:mem",
],
@ -2452,6 +2473,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -2508,6 +2530,7 @@ grpc_cc_library(
"//src/core:grpc_backend_metric_provider",
"//src/core:grpc_crl_provider",
"//src/core:grpc_service_config",
"//src/core:grpc_transport_chttp2_server",
"//src/core:grpc_transport_inproc",
"//src/core:json",
"//src/core:json_reader",
@ -2535,6 +2558,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -2566,6 +2590,7 @@ grpc_cc_library(
"grpc_security_base",
"grpc_service_config_impl",
"grpc_trace",
"grpc_transport_chttp2",
"grpc_unsecure",
"grpcpp_backend_metric_recorder",
"grpcpp_call_metric_recorder",
@ -2587,6 +2612,7 @@ grpc_cc_library(
"//src/core:grpc_backend_metric_provider",
"//src/core:grpc_insecure_credentials",
"//src/core:grpc_service_config",
"//src/core:grpc_transport_chttp2_server",
"//src/core:grpc_transport_inproc",
"//src/core:ref_counted",
"//src/core:resource_quota",
@ -2689,6 +2715,7 @@ grpc_cc_library(
],
external_deps = [
"absl/base:core_headers",
"absl/log:log",
"absl/strings",
],
language = "c++",
@ -2965,6 +2992,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/container:inlined_vector",
"absl/log:check",
"absl/log:log",
],
language = "c++",
visibility = ["@grpc:client_channel"],
@ -2985,7 +3013,10 @@ grpc_cc_library(
name = "grpc_trace",
srcs = ["//src/core:lib/debug/trace.cc"],
hdrs = ["//src/core:lib/debug/trace.h"],
external_deps = ["absl/strings"],
external_deps = [
"absl/log:log",
"absl/strings",
],
language = "c++",
visibility = ["@grpc:trace"],
deps = [
@ -3130,6 +3161,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/container:inlined_vector",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/strings:str_format",
],
@ -3166,6 +3198,7 @@ grpc_cc_library(
],
external_deps = [
"absl/base:core_headers",
"absl/log:log",
"absl/status",
"absl/strings",
"absl/types:optional",
@ -3212,6 +3245,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings:str_format",
],
visibility = [
@ -3243,6 +3277,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -3277,6 +3312,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings",
"absl/strings:str_format",
],
@ -3305,6 +3341,9 @@ grpc_cc_library(
hdrs = [
"//src/core:lib/iomgr/internal_errqueue.h",
],
external_deps = [
"absl/log:log",
],
tags = ["nofixdeps"],
visibility = ["@grpc:iomgr_internal_errqueue"],
deps = [
@ -3323,6 +3362,7 @@ grpc_cc_library(
"//src/core:lib/iomgr/buffer_list.h",
],
external_deps = [
"absl/log:log",
"absl/strings",
"absl/strings:str_format",
"absl/types:optional",
@ -3369,6 +3409,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -3536,6 +3577,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -3569,6 +3611,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/strings",
"@com_google_protobuf//upb:base",
@ -3611,6 +3654,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/strings",
],
@ -3667,6 +3711,7 @@ grpc_cc_library(
"absl/container:inlined_vector",
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -3801,6 +3846,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -3865,6 +3911,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/functional:bind_front",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -3919,6 +3966,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/strings",
"absl/types:optional",
@ -3963,6 +4011,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
],
language = "c++",
visibility = [
@ -3990,6 +4039,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -4050,7 +4100,10 @@ grpc_cc_library(
"//src/core:lib/security/security_connector/load_system_roots_supported.h",
"//src/core:lib/security/util/json_util.h",
],
external_deps = ["absl/strings"],
external_deps = [
"absl/log:log",
"absl/strings",
],
language = "c++",
visibility = ["@grpc:public"],
deps = [
@ -4082,6 +4135,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings",
"@com_google_protobuf//upb:base",
"@com_google_protobuf//upb:mem",
@ -4142,6 +4196,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/types:span",
"libcrypto",
"libssl",
@ -4173,6 +4228,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/memory",
"libssl",
],
@ -4204,6 +4260,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -4252,6 +4309,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -4337,6 +4395,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/cleanup",
"absl/log:check",
"absl/log:log",
"absl/memory",
"absl/status",
"absl/status:statusor",
@ -4503,6 +4562,7 @@ grpc_cc_library(
external_deps = [
"absl/functional:function_ref",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/strings",
],
@ -4559,6 +4619,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/random:bit_gen_ref",
"absl/status",
"absl/strings",
@ -4601,6 +4662,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings",
],
deps = [
@ -4714,6 +4776,7 @@ grpc_cc_library(
"absl/container:flat_hash_map",
"absl/hash",
"absl/log:check",
"absl/log:log",
"absl/meta:type_traits",
"absl/random",
"absl/random:bit_gen_ref",
@ -4840,6 +4903,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings",
"absl/types:span",
],

45
CMakeLists.txt generated

@ -1052,6 +1052,7 @@ if(gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx dualstack_socket_test)
endif()
add_dependencies(buildtests_cxx dump_args_test)
add_dependencies(buildtests_cxx duplicate_header_bad_client_test)
add_dependencies(buildtests_cxx empty_batch_test)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX)
@ -2501,6 +2502,7 @@ add_library(grpc
src/core/lib/transport/call_spine.cc
src/core/lib/transport/connectivity_state.cc
src/core/lib/transport/error_utils.cc
src/core/lib/transport/interception_chain.cc
src/core/lib/transport/message.cc
src/core/lib/transport/metadata.cc
src/core/lib/transport/metadata_batch.cc
@ -2746,6 +2748,7 @@ foreach(_hdr
include/grpc/impl/propagation_bits.h
include/grpc/impl/slice_type.h
include/grpc/load_reporting.h
include/grpc/passive_listener.h
include/grpc/slice.h
include/grpc/slice_buffer.h
include/grpc/status.h
@ -3253,6 +3256,7 @@ add_library(grpc_unsecure
src/core/lib/transport/call_spine.cc
src/core/lib/transport/connectivity_state.cc
src/core/lib/transport/error_utils.cc
src/core/lib/transport/interception_chain.cc
src/core/lib/transport/message.cc
src/core/lib/transport/metadata.cc
src/core/lib/transport/metadata_batch.cc
@ -3446,6 +3450,7 @@ foreach(_hdr
include/grpc/impl/propagation_bits.h
include/grpc/impl/slice_type.h
include/grpc/load_reporting.h
include/grpc/passive_listener.h
include/grpc/slice.h
include/grpc/slice_buffer.h
include/grpc/status.h
@ -4314,6 +4319,7 @@ foreach(_hdr
include/grpcpp/impl/service_type.h
include/grpcpp/impl/status.h
include/grpcpp/impl/sync.h
include/grpcpp/passive_listener.h
include/grpcpp/resource_quota.h
include/grpcpp/security/audit_logging.h
include/grpcpp/security/auth_context.h
@ -5054,6 +5060,7 @@ foreach(_hdr
include/grpcpp/impl/service_type.h
include/grpcpp/impl/status.h
include/grpcpp/impl/sync.h
include/grpcpp/passive_listener.h
include/grpcpp/resource_quota.h
include/grpcpp/security/audit_logging.h
include/grpcpp/security/auth_context.h
@ -5361,6 +5368,7 @@ add_library(grpc_authorization_provider
src/core/lib/transport/call_spine.cc
src/core/lib/transport/connectivity_state.cc
src/core/lib/transport/error_utils.cc
src/core/lib/transport/interception_chain.cc
src/core/lib/transport/message.cc
src/core/lib/transport/metadata.cc
src/core/lib/transport/metadata_batch.cc
@ -5504,6 +5512,7 @@ foreach(_hdr
include/grpc/impl/propagation_bits.h
include/grpc/impl/slice_type.h
include/grpc/load_reporting.h
include/grpc/passive_listener.h
include/grpc/slice.h
include/grpc/slice_buffer.h
include/grpc/status.h
@ -12385,6 +12394,41 @@ endif()
endif()
if(gRPC_BUILD_TESTS)
add_executable(dump_args_test
src/core/lib/gprpp/dump_args.cc
test/core/gprpp/dump_args_test.cc
)
target_compile_features(dump_args_test PUBLIC cxx_std_14)
target_include_directories(dump_args_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(dump_args_test
${_gRPC_ALLTARGETS_LIBRARIES}
gtest
absl::any_invocable
absl::check
)
endif()
if(gRPC_BUILD_TESTS)
add_executable(duplicate_header_bad_client_test
test/core/bad_client/bad_client.cc
test/core/bad_client/tests/duplicate_header.cc
@ -26833,6 +26877,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
${_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
test/core/event_engine/event_engine_test_utils.cc
test/core/test_util/cmdline.cc
test/core/test_util/fuzzer_util.cc
test/core/test_util/grpc_profiler.cc

2
Makefile generated

@ -1387,6 +1387,7 @@ LIBGRPC_SRC = \
src/core/lib/transport/call_spine.cc \
src/core/lib/transport/connectivity_state.cc \
src/core/lib/transport/error_utils.cc \
src/core/lib/transport/interception_chain.cc \
src/core/lib/transport/message.cc \
src/core/lib/transport/metadata.cc \
src/core/lib/transport/metadata_batch.cc \
@ -1775,6 +1776,7 @@ PUBLIC_HEADERS_C += \
include/grpc/impl/propagation_bits.h \
include/grpc/impl/slice_type.h \
include/grpc/load_reporting.h \
include/grpc/passive_listener.h \
include/grpc/slice.h \
include/grpc/slice_buffer.h \
include/grpc/status.h \

4
Package.swift generated

@ -93,6 +93,7 @@ let package = Package(
"include/grpc/impl/propagation_bits.h",
"include/grpc/impl/slice_type.h",
"include/grpc/load_reporting.h",
"include/grpc/passive_listener.h",
"include/grpc/slice.h",
"include/grpc/slice_buffer.h",
"include/grpc/status.h",
@ -1748,6 +1749,7 @@ let package = Package(
"src/core/lib/transport/bdp_estimator.h",
"src/core/lib/transport/call_arena_allocator.cc",
"src/core/lib/transport/call_arena_allocator.h",
"src/core/lib/transport/call_destination.h",
"src/core/lib/transport/call_filters.cc",
"src/core/lib/transport/call_filters.h",
"src/core/lib/transport/call_final_info.cc",
@ -1760,6 +1762,8 @@ let package = Package(
"src/core/lib/transport/error_utils.cc",
"src/core/lib/transport/error_utils.h",
"src/core/lib/transport/http2_errors.h",
"src/core/lib/transport/interception_chain.cc",
"src/core/lib/transport/interception_chain.h",
"src/core/lib/transport/message.cc",
"src/core/lib/transport/message.h",
"src/core/lib/transport/metadata.cc",

@ -34,9 +34,8 @@ EXPERIMENT_ENABLES = {
"pending_queue_cap": "pending_queue_cap",
"pick_first_new": "pick_first_new",
"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",
"promise_based_inproc_transport": "event_engine_client,event_engine_listener,promise_based_client_call,promise_based_inproc_transport,promise_based_server_call",
"chaotic_good": "chaotic_good,event_engine_client,event_engine_listener,promise_based_client_call",
"promise_based_inproc_transport": "event_engine_client,event_engine_listener,promise_based_client_call,promise_based_inproc_transport",
"rstpit": "rstpit",
"schedule_cancellation_over_write": "schedule_cancellation_over_write",
"server_privacy": "server_privacy",
@ -59,17 +58,10 @@ EXPERIMENTS = {
"dbg": {
},
"off": {
"core_end2end_test": [
"event_engine_client",
"promise_based_server_call",
],
"endpoint_test": [
"tcp_frame_size_tuning",
"tcp_rcv_lowat",
],
"event_engine_client_test": [
"event_engine_client",
],
"flow_control_test": [
"multiping",
"peer_state_based_framing",
@ -77,9 +69,6 @@ EXPERIMENTS = {
"tcp_frame_size_tuning",
"tcp_rcv_lowat",
],
"logging_test": [
"promise_based_server_call",
],
"resource_quota_test": [
"free_large_allocator",
"unconstrained_max_quota_buffer_size",
@ -87,11 +76,15 @@ EXPERIMENTS = {
},
"on": {
"core_end2end_test": [
"event_engine_client",
"event_engine_listener",
],
"cpp_lb_end2end_test": [
"pick_first_new",
],
"event_engine_client_test": [
"event_engine_client",
],
"event_engine_listener_test": [
"event_engine_listener",
],
@ -107,9 +100,6 @@ EXPERIMENTS = {
"dbg": {
},
"off": {
"core_end2end_test": [
"promise_based_server_call",
],
"endpoint_test": [
"tcp_frame_size_tuning",
"tcp_rcv_lowat",
@ -121,9 +111,6 @@ EXPERIMENTS = {
"tcp_frame_size_tuning",
"tcp_rcv_lowat",
],
"logging_test": [
"promise_based_server_call",
],
"resource_quota_test": [
"free_large_allocator",
"unconstrained_max_quota_buffer_size",
@ -149,7 +136,6 @@ EXPERIMENTS = {
"chaotic_good",
"event_engine_client",
"promise_based_client_call",
"promise_based_server_call",
],
"endpoint_test": [
"tcp_frame_size_tuning",
@ -168,9 +154,6 @@ EXPERIMENTS = {
"lame_client_test": [
"promise_based_client_call",
],
"logging_test": [
"promise_based_server_call",
],
"resource_quota_test": [
"free_large_allocator",
"unconstrained_max_quota_buffer_size",

@ -198,6 +198,7 @@ libs:
- include/grpc/impl/propagation_bits.h
- include/grpc/impl/slice_type.h
- include/grpc/load_reporting.h
- include/grpc/passive_listener.h
- include/grpc/slice.h
- include/grpc/slice_buffer.h
- include/grpc/status.h
@ -1109,6 +1110,7 @@ libs:
- src/core/lib/transport/batch_builder.h
- src/core/lib/transport/bdp_estimator.h
- src/core/lib/transport/call_arena_allocator.h
- src/core/lib/transport/call_destination.h
- src/core/lib/transport/call_filters.h
- src/core/lib/transport/call_final_info.h
- src/core/lib/transport/call_spine.h
@ -1116,6 +1118,7 @@ libs:
- src/core/lib/transport/custom_metadata.h
- src/core/lib/transport/error_utils.h
- src/core/lib/transport/http2_errors.h
- src/core/lib/transport/interception_chain.h
- src/core/lib/transport/message.h
- src/core/lib/transport/metadata.h
- src/core/lib/transport/metadata_batch.h
@ -1920,6 +1923,7 @@ libs:
- src/core/lib/transport/call_spine.cc
- src/core/lib/transport/connectivity_state.cc
- src/core/lib/transport/error_utils.cc
- src/core/lib/transport/interception_chain.cc
- src/core/lib/transport/message.cc
- src/core/lib/transport/metadata.cc
- src/core/lib/transport/metadata_batch.cc
@ -2182,6 +2186,7 @@ libs:
- include/grpc/impl/propagation_bits.h
- include/grpc/impl/slice_type.h
- include/grpc/load_reporting.h
- include/grpc/passive_listener.h
- include/grpc/slice.h
- include/grpc/slice_buffer.h
- include/grpc/status.h
@ -2607,6 +2612,7 @@ libs:
- src/core/lib/transport/batch_builder.h
- src/core/lib/transport/bdp_estimator.h
- src/core/lib/transport/call_arena_allocator.h
- src/core/lib/transport/call_destination.h
- src/core/lib/transport/call_filters.h
- src/core/lib/transport/call_final_info.h
- src/core/lib/transport/call_spine.h
@ -2614,6 +2620,7 @@ libs:
- src/core/lib/transport/custom_metadata.h
- src/core/lib/transport/error_utils.h
- src/core/lib/transport/http2_errors.h
- src/core/lib/transport/interception_chain.h
- src/core/lib/transport/message.h
- src/core/lib/transport/metadata.h
- src/core/lib/transport/metadata_batch.h
@ -3030,6 +3037,7 @@ libs:
- src/core/lib/transport/call_spine.cc
- src/core/lib/transport/connectivity_state.cc
- src/core/lib/transport/error_utils.cc
- src/core/lib/transport/interception_chain.cc
- src/core/lib/transport/message.cc
- src/core/lib/transport/metadata.cc
- src/core/lib/transport/metadata_batch.cc
@ -3786,6 +3794,7 @@ libs:
- include/grpcpp/impl/service_type.h
- include/grpcpp/impl/status.h
- include/grpcpp/impl/sync.h
- include/grpcpp/passive_listener.h
- include/grpcpp/resource_quota.h
- include/grpcpp/security/audit_logging.h
- include/grpcpp/security/auth_context.h
@ -4213,6 +4222,7 @@ libs:
- include/grpcpp/impl/service_type.h
- include/grpcpp/impl/status.h
- include/grpcpp/impl/sync.h
- include/grpcpp/passive_listener.h
- include/grpcpp/resource_quota.h
- include/grpcpp/security/audit_logging.h
- include/grpcpp/security/auth_context.h
@ -4361,6 +4371,7 @@ libs:
- include/grpc/impl/propagation_bits.h
- include/grpc/impl/slice_type.h
- include/grpc/load_reporting.h
- include/grpc/passive_listener.h
- include/grpc/slice.h
- include/grpc/slice_buffer.h
- include/grpc/status.h
@ -4681,6 +4692,7 @@ libs:
- src/core/lib/surface/wait_for_cq_end_op.h
- src/core/lib/transport/batch_builder.h
- src/core/lib/transport/call_arena_allocator.h
- src/core/lib/transport/call_destination.h
- src/core/lib/transport/call_filters.h
- src/core/lib/transport/call_final_info.h
- src/core/lib/transport/call_spine.h
@ -4688,6 +4700,7 @@ libs:
- src/core/lib/transport/custom_metadata.h
- src/core/lib/transport/error_utils.h
- src/core/lib/transport/http2_errors.h
- src/core/lib/transport/interception_chain.h
- src/core/lib/transport/message.h
- src/core/lib/transport/metadata.h
- src/core/lib/transport/metadata_batch.h
@ -4984,6 +4997,7 @@ libs:
- src/core/lib/transport/call_spine.cc
- src/core/lib/transport/connectivity_state.cc
- src/core/lib/transport/error_utils.cc
- src/core/lib/transport/interception_chain.cc
- src/core/lib/transport/message.cc
- src/core/lib/transport/metadata.cc
- src/core/lib/transport/metadata_batch.cc
@ -8656,6 +8670,20 @@ targets:
- linux
- posix
- mac
- name: dump_args_test
gtest: true
build: test
language: c++
headers:
- src/core/lib/gprpp/dump_args.h
src:
- src/core/lib/gprpp/dump_args.cc
- test/core/gprpp/dump_args_test.cc
deps:
- gtest
- absl/functional:any_invocable
- absl/log:check
uses_polling: false
- name: duplicate_header_bad_client_test
gtest: true
build: test
@ -17784,6 +17812,7 @@ targets:
build: test
language: c++
headers:
- test/core/event_engine/event_engine_test_utils.h
- test/core/test_util/cmdline.h
- test/core/test_util/evaluate_args_test_util.h
- test/core/test_util/fuzzer_util.h
@ -17799,6 +17828,7 @@ targets:
- src/proto/grpc/testing/echo_messages.proto
- src/proto/grpc/testing/simple_messages.proto
- src/proto/grpc/testing/xds/v3/orca_load_report.proto
- test/core/event_engine/event_engine_test_utils.cc
- test/core/test_util/cmdline.cc
- test/core/test_util/fuzzer_util.cc
- test/core/test_util/grpc_profiler.cc

1
config.m4 generated

@ -762,6 +762,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/transport/call_spine.cc \
src/core/lib/transport/connectivity_state.cc \
src/core/lib/transport/error_utils.cc \
src/core/lib/transport/interception_chain.cc \
src/core/lib/transport/message.cc \
src/core/lib/transport/metadata.cc \
src/core/lib/transport/metadata_batch.cc \

1
config.w32 generated

@ -727,6 +727,7 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\transport\\call_spine.cc " +
"src\\core\\lib\\transport\\connectivity_state.cc " +
"src\\core\\lib\\transport\\error_utils.cc " +
"src\\core\\lib\\transport\\interception_chain.cc " +
"src\\core\\lib\\transport\\message.cc " +
"src\\core\\lib\\transport\\metadata.cc " +
"src\\core\\lib\\transport\\metadata_batch.cc " +

5
gRPC-C++.podspec generated

@ -176,6 +176,7 @@ Pod::Spec.new do |s|
'include/grpcpp/impl/service_type.h',
'include/grpcpp/impl/status.h',
'include/grpcpp/impl/sync.h',
'include/grpcpp/passive_listener.h',
'include/grpcpp/resource_quota.h',
'include/grpcpp/security/audit_logging.h',
'include/grpcpp/security/auth_context.h',
@ -1212,6 +1213,7 @@ Pod::Spec.new do |s|
'src/core/lib/transport/batch_builder.h',
'src/core/lib/transport/bdp_estimator.h',
'src/core/lib/transport/call_arena_allocator.h',
'src/core/lib/transport/call_destination.h',
'src/core/lib/transport/call_filters.h',
'src/core/lib/transport/call_final_info.h',
'src/core/lib/transport/call_spine.h',
@ -1219,6 +1221,7 @@ Pod::Spec.new do |s|
'src/core/lib/transport/custom_metadata.h',
'src/core/lib/transport/error_utils.h',
'src/core/lib/transport/http2_errors.h',
'src/core/lib/transport/interception_chain.h',
'src/core/lib/transport/message.h',
'src/core/lib/transport/metadata.h',
'src/core/lib/transport/metadata_batch.h',
@ -2481,6 +2484,7 @@ Pod::Spec.new do |s|
'src/core/lib/transport/batch_builder.h',
'src/core/lib/transport/bdp_estimator.h',
'src/core/lib/transport/call_arena_allocator.h',
'src/core/lib/transport/call_destination.h',
'src/core/lib/transport/call_filters.h',
'src/core/lib/transport/call_final_info.h',
'src/core/lib/transport/call_spine.h',
@ -2488,6 +2492,7 @@ Pod::Spec.new do |s|
'src/core/lib/transport/custom_metadata.h',
'src/core/lib/transport/error_utils.h',
'src/core/lib/transport/http2_errors.h',
'src/core/lib/transport/interception_chain.h',
'src/core/lib/transport/message.h',
'src/core/lib/transport/metadata.h',
'src/core/lib/transport/metadata_batch.h',

6
gRPC-Core.podspec generated

@ -168,6 +168,7 @@ Pod::Spec.new do |s|
'include/grpc/impl/propagation_bits.h',
'include/grpc/impl/slice_type.h',
'include/grpc/load_reporting.h',
'include/grpc/passive_listener.h',
'include/grpc/slice.h',
'include/grpc/slice_buffer.h',
'include/grpc/status.h',
@ -1863,6 +1864,7 @@ Pod::Spec.new do |s|
'src/core/lib/transport/bdp_estimator.h',
'src/core/lib/transport/call_arena_allocator.cc',
'src/core/lib/transport/call_arena_allocator.h',
'src/core/lib/transport/call_destination.h',
'src/core/lib/transport/call_filters.cc',
'src/core/lib/transport/call_filters.h',
'src/core/lib/transport/call_final_info.cc',
@ -1875,6 +1877,8 @@ Pod::Spec.new do |s|
'src/core/lib/transport/error_utils.cc',
'src/core/lib/transport/error_utils.h',
'src/core/lib/transport/http2_errors.h',
'src/core/lib/transport/interception_chain.cc',
'src/core/lib/transport/interception_chain.h',
'src/core/lib/transport/message.cc',
'src/core/lib/transport/message.h',
'src/core/lib/transport/metadata.cc',
@ -3260,6 +3264,7 @@ Pod::Spec.new do |s|
'src/core/lib/transport/batch_builder.h',
'src/core/lib/transport/bdp_estimator.h',
'src/core/lib/transport/call_arena_allocator.h',
'src/core/lib/transport/call_destination.h',
'src/core/lib/transport/call_filters.h',
'src/core/lib/transport/call_final_info.h',
'src/core/lib/transport/call_spine.h',
@ -3267,6 +3272,7 @@ Pod::Spec.new do |s|
'src/core/lib/transport/custom_metadata.h',
'src/core/lib/transport/error_utils.h',
'src/core/lib/transport/http2_errors.h',
'src/core/lib/transport/interception_chain.h',
'src/core/lib/transport/message.h',
'src/core/lib/transport/metadata.h',
'src/core/lib/transport/metadata_batch.h',

4
grpc.gemspec generated

@ -99,6 +99,7 @@ Gem::Specification.new do |s|
s.files += %w( include/grpc/impl/propagation_bits.h )
s.files += %w( include/grpc/impl/slice_type.h )
s.files += %w( include/grpc/load_reporting.h )
s.files += %w( include/grpc/passive_listener.h )
s.files += %w( include/grpc/slice.h )
s.files += %w( include/grpc/slice_buffer.h )
s.files += %w( include/grpc/status.h )
@ -1750,6 +1751,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/transport/bdp_estimator.h )
s.files += %w( src/core/lib/transport/call_arena_allocator.cc )
s.files += %w( src/core/lib/transport/call_arena_allocator.h )
s.files += %w( src/core/lib/transport/call_destination.h )
s.files += %w( src/core/lib/transport/call_filters.cc )
s.files += %w( src/core/lib/transport/call_filters.h )
s.files += %w( src/core/lib/transport/call_final_info.cc )
@ -1762,6 +1764,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/transport/error_utils.cc )
s.files += %w( src/core/lib/transport/error_utils.h )
s.files += %w( src/core/lib/transport/http2_errors.h )
s.files += %w( src/core/lib/transport/interception_chain.cc )
s.files += %w( src/core/lib/transport/interception_chain.h )
s.files += %w( src/core/lib/transport/message.cc )
s.files += %w( src/core/lib/transport/message.h )
s.files += %w( src/core/lib/transport/metadata.cc )

@ -38,6 +38,7 @@ header "byte_buffer.h"
header "impl/propagation_bits.h"
header "impl/slice_type.h"
header "load_reporting.h"
header "passive_listener.h"
header "slice.h"
header "slice_buffer.h"
header "status.h"

@ -0,0 +1,62 @@
// 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_PASSIVE_LISTENER_H
#define GRPC_PASSIVE_LISTENER_H
#include <memory>
#include <grpc/event_engine/event_engine.h>
#include <grpc/grpc.h>
// #include <grpc/support/port_platform.h>
namespace grpc_core {
class Server;
namespace experimental {
class PassiveListenerImpl;
/// -- EXPERIMENTAL API --
/// Interface for used for Server Endpoint injection.
class PassiveListener {
public:
virtual ~PassiveListener() = default;
/// -- EXPERIMENTAL API --
///
/// Takes an Endpoint for an established connection, and treats it as if the
/// connection had been accepted by the server.
///
/// The server must be started before endpoints can be accepted.
virtual absl::Status AcceptConnectedEndpoint(
std::unique_ptr<grpc_event_engine::experimental::EventEngine::Endpoint>
endpoint) = 0;
/// -- EXPERIMENTAL API --
///
/// Takes a connected file descriptor, and treats it as if the server had
/// accepted the connection itself.
///
/// Returns a failure status if the server's active EventEngine does not
/// support Endpoint creation from fds.
virtual absl::Status AcceptConnectedFd(int fd) = 0;
};
} // namespace experimental
} // namespace grpc_core
absl::Status grpc_server_add_passive_listener(
grpc_core::Server* server, grpc_server_credentials* credentials,
std::shared_ptr<grpc_core::experimental::PassiveListenerImpl>
passive_listener);
#endif /* GRPC_PASSIVE_LISTENER_H */

@ -99,12 +99,6 @@ GPRAPI void gpr_assertion_failed(const char* filename, int line,
} \
} while (0)
#ifndef NDEBUG
#define GPR_DEBUG_ASSERT(x) GPR_ASSERT(x)
#else
#define GPR_DEBUG_ASSERT(x) GPR_ASSERT(true || (x))
#endif
#ifdef __cplusplus
}
#endif

@ -0,0 +1,27 @@
// 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 GRPCPP_PASSIVE_LISTENER_H
#define GRPCPP_PASSIVE_LISTENER_H
#include <grpc/passive_listener.h>
namespace grpc {
namespace experimental {
using grpc_core::experimental::PassiveListener;
} // namespace experimental
} // namespace grpc
#endif // GRPCPP_PASSIVE_LISTENER_H

@ -84,6 +84,7 @@ class ServerCredentials : private grpc::internal::GrpcLibrary {
// Needed for access to AddPortToServer.
friend class Server;
// Needed for access to c_creds_.
friend class ServerBuilder;
friend std::shared_ptr<ServerCredentials> grpc::XdsServerCredentials(
const std::shared_ptr<ServerCredentials>& fallback_credentials);

@ -103,6 +103,8 @@ class TlsCredentialsOptions {
// call is covered by the cert that the peer presented.
// We will perform such checks by default. This should be disabled if
// verifiers other than the host name verifier is used.
// Deprecated: This function will be removed in the 1.66 release. This will be
// replaced by and handled within the custom verifier settings.
void set_check_call_host(bool check_call_host);
// Deprecated in favor of set_crl_provider. The
@ -111,6 +113,8 @@ class TlsCredentialsOptions {
// If set, gRPC will read all hashed x.509 CRL files in the directory and
// enforce the CRL files on all TLS handshakes. Only supported for OpenSSL
// version > 1.1.
// Deprecated: This function will be removed in the 1.66 release. Use the
// set_crl_provider function instead.
void set_crl_directory(const std::string& path);
void set_crl_provider(std::shared_ptr<CrlProvider> crl_provider);
@ -184,6 +188,7 @@ class TlsServerCredentialsOptions final : public TlsCredentialsOptions {
// WARNING: This API is extremely dangerous and should not be used. If the
// server's trust bundle is too large, then the TLS server will be unable to
// form a ServerHello, and hence will be unusable.
// Deprecated: This function will be removed in the 1.66 release.
void set_send_client_ca_list(bool send_client_ca_list);
private:

@ -25,13 +25,17 @@
#include <vector>
#include <grpc/compression.h>
#include <grpc/event_engine/event_engine.h>
#include <grpc/passive_listener.h>
#include <grpc/support/cpu.h>
#include <grpc/support/port_platform.h>
#include <grpc/support/workaround_list.h>
#include <grpcpp/impl/channel_argument_option.h>
#include <grpcpp/impl/server_builder_option.h>
#include <grpcpp/impl/server_builder_plugin.h>
#include <grpcpp/passive_listener.h>
#include <grpcpp/security/authorization_policy_provider.h>
#include <grpcpp/security/server_credentials.h>
#include <grpcpp/server.h>
#include <grpcpp/support/config.h>
#include <grpcpp/support/server_interceptor.h>
@ -291,6 +295,18 @@ class ServerBuilder {
void EnableCallMetricRecording(
experimental::ServerMetricRecorder* server_metric_recorder = nullptr);
// Creates a passive listener for Server Endpoint injection.
///
/// \a PasiveListener lets applications provide pre-established connections
/// to gRPC Servers. The server will behave as if it accepted the connection
/// itself on its own listening addresses.
///
/// This can be called multiple times to create passive listeners with
/// different server credentials.
ServerBuilder& AddPassiveListener(
std::shared_ptr<grpc::ServerCredentials> creds,
std::unique_ptr<grpc::experimental::PassiveListener>& passive_listener);
private:
ServerBuilder* builder_;
};
@ -364,6 +380,17 @@ class ServerBuilder {
private:
friend class grpc::testing::ServerBuilderPluginTest;
struct UnstartedPassiveListener {
std::weak_ptr<grpc_core::experimental::PassiveListenerImpl>
passive_listener;
std::shared_ptr<grpc::ServerCredentials> credentials;
UnstartedPassiveListener(
std::weak_ptr<grpc_core::experimental::PassiveListenerImpl> listener,
std::shared_ptr<grpc::ServerCredentials> creds)
: passive_listener(std::move(listener)),
credentials(std::move(creds)) {}
};
struct SyncServerSettings {
SyncServerSettings()
: num_cqs(1), min_pollers(1), max_pollers(2), cq_timeout_msec(10000) {}
@ -388,6 +415,7 @@ class ServerBuilder {
std::vector<std::unique_ptr<grpc::ServerBuilderOption>> options_;
std::vector<std::unique_ptr<NamedService>> services_;
std::vector<Port> ports_;
std::vector<UnstartedPassiveListener> unstarted_passive_listeners_;
SyncServerSettings sync_server_settings_;

4
package.xml generated

@ -81,6 +81,7 @@
<file baseinstalldir="/" name="include/grpc/impl/propagation_bits.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/slice_type.h" role="src" />
<file baseinstalldir="/" name="include/grpc/load_reporting.h" role="src" />
<file baseinstalldir="/" name="include/grpc/passive_listener.h" role="src" />
<file baseinstalldir="/" name="include/grpc/slice.h" role="src" />
<file baseinstalldir="/" name="include/grpc/slice_buffer.h" role="src" />
<file baseinstalldir="/" name="include/grpc/status.h" role="src" />
@ -1732,6 +1733,7 @@
<file baseinstalldir="/" name="src/core/lib/transport/bdp_estimator.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/call_arena_allocator.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/call_arena_allocator.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/call_destination.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/call_filters.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/call_filters.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/call_final_info.cc" role="src" />
@ -1744,6 +1746,8 @@
<file baseinstalldir="/" name="src/core/lib/transport/error_utils.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/error_utils.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/http2_errors.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/interception_chain.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/interception_chain.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/message.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/message.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata.cc" role="src" />

@ -48,6 +48,25 @@ grpc_cc_library(
language = "c++",
)
grpc_cc_library(
name = "dump_args",
srcs = [
"lib/gprpp/dump_args.cc",
],
hdrs = [
"lib/gprpp/dump_args.h",
],
external_deps = [
"absl/functional:any_invocable",
"absl/log:check",
"absl/strings",
],
language = "c++",
deps = [
"//:gpr_platform",
],
)
grpc_cc_library(
name = "slice_cast",
hdrs = [
@ -197,6 +216,7 @@ grpc_cc_library(
external_deps = [
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/strings",
],
language = "c++",
@ -395,6 +415,7 @@ grpc_cc_library(
"lib/gprpp/validation_errors.h",
],
external_deps = [
"absl/log:log",
"absl/status",
"absl/strings",
],
@ -511,7 +532,10 @@ grpc_cc_library(
grpc_cc_library(
name = "map_pipe",
external_deps = ["absl/status"],
external_deps = [
"absl/log:log",
"absl/status",
],
language = "c++",
public_hdrs = [
"lib/promise/map_pipe.h",
@ -540,6 +564,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/strings",
"absl/strings:str_format",
],
@ -639,7 +664,10 @@ grpc_cc_library(
grpc_cc_library(
name = "promise_like",
external_deps = ["absl/meta:type_traits"],
external_deps = [
"absl/functional:any_invocable",
"absl/meta:type_traits",
],
language = "c++",
public_hdrs = [
"lib/promise/detail/promise_like.h",
@ -754,6 +782,7 @@ grpc_cc_library(
name = "join_state",
external_deps = [
"absl/log:check",
"absl/log:log",
],
language = "c++",
public_hdrs = [
@ -843,6 +872,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/strings",
],
language = "c++",
@ -982,6 +1012,7 @@ grpc_cc_library(
name = "latch",
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings",
],
language = "c++",
@ -1000,6 +1031,7 @@ grpc_cc_library(
name = "inter_activity_latch",
external_deps = [
"absl/base:core_headers",
"absl/log:log",
"absl/strings",
],
language = "c++",
@ -1022,6 +1054,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings",
"absl/strings:str_format",
"absl/types:optional",
@ -1045,6 +1078,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings",
"absl/types:optional",
"absl/types:variant",
@ -1156,6 +1190,7 @@ grpc_cc_library(
name = "for_each",
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/strings",
],
@ -1178,6 +1213,7 @@ grpc_cc_library(
name = "ref_counted",
external_deps = [
"absl/log:check",
"absl/log:log",
],
language = "c++",
public_hdrs = ["lib/gprpp/ref_counted.h"],
@ -1194,6 +1230,7 @@ grpc_cc_library(
name = "dual_ref_counted",
external_deps = [
"absl/log:check",
"absl/log:log",
],
language = "c++",
public_hdrs = ["lib/gprpp/dual_ref_counted.h"],
@ -1389,6 +1426,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/container:flat_hash_set",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/strings",
"absl/types:optional",
@ -1439,6 +1477,9 @@ grpc_cc_library(
hdrs = [
"lib/resource_quota/arena.h",
],
external_deps = [
"absl/log:log",
],
visibility = [
"@grpc:alt_grpc_base_legacy",
],
@ -1538,6 +1579,9 @@ grpc_cc_library(
hdrs = [
"lib/slice/slice_refcount.h",
],
external_deps = [
"absl/log:log",
],
public_hdrs = [
"//:include/grpc/slice.h",
],
@ -1605,6 +1649,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/strings:str_format",
],
@ -1632,6 +1677,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings:str_format",
],
visibility = ["@grpc:alt_grpc_base_legacy"],
@ -1653,6 +1699,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings:str_format",
"absl/types:optional",
],
@ -1734,6 +1781,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
],
deps = [
"//:config_vars",
@ -1883,6 +1931,7 @@ grpc_cc_library(
"absl/container:flat_hash_set",
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/time",
"absl/types:optional",
],
@ -1933,6 +1982,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/time",
"absl/types:optional",
],
@ -2090,6 +2140,7 @@ grpc_cc_library(
"absl/container:inlined_vector",
"absl/functional:function_ref",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -2196,6 +2247,7 @@ grpc_cc_library(
],
external_deps = [
"absl/functional:any_invocable",
"absl/log:log",
"absl/status",
"absl/types:optional",
],
@ -2220,6 +2272,7 @@ grpc_cc_library(
"absl/functional:any_invocable",
"absl/hash",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -2281,6 +2334,7 @@ grpc_cc_library(
external_deps = [
"absl/cleanup",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -2313,6 +2367,7 @@ grpc_cc_library(
external_deps = [
"absl/cleanup",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -2340,6 +2395,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -2376,6 +2432,7 @@ grpc_cc_library(
"absl/functional:any_invocable",
"absl/hash",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -2418,6 +2475,7 @@ grpc_cc_library(
hdrs = ["lib/event_engine/windows/windows_engine.h"],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -2472,6 +2530,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/strings:str_format",
],
@ -2501,6 +2560,7 @@ grpc_cc_library(
"absl/cleanup",
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/strings:str_format",
],
@ -2529,6 +2589,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings:str_format",
@ -2563,6 +2624,7 @@ grpc_cc_library(
external_deps = [
"absl/container:flat_hash_map",
"absl/log:check",
"absl/log:log",
"absl/strings",
"absl/strings:str_format",
],
@ -2597,6 +2659,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -2623,6 +2686,9 @@ grpc_cc_library(
hdrs = [
"lib/event_engine/trace.h",
],
external_deps = [
"absl/log:log",
],
deps = [
"//:gpr",
"//:gpr_platform",
@ -2813,6 +2879,7 @@ grpc_cc_library(
"absl/functional:any_invocable",
"absl/hash",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -2869,6 +2936,7 @@ grpc_cc_library(
hdrs = ["lib/transport/bdp_estimator.h"],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings",
],
deps = [
@ -3054,6 +3122,7 @@ grpc_cc_library(
external_deps = [
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/strings",
"absl/types:optional",
],
@ -3064,6 +3133,7 @@ grpc_cc_library(
"channel_fwd",
"channel_stack_trace",
"channel_stack_type",
"interception_chain",
"//:channel_stack_builder",
"//:debug_location",
"//:gpr",
@ -3081,6 +3151,7 @@ grpc_cc_library(
deps = [
"channel_args",
"//:channelz",
"//:event_engine_base_hdrs",
"//:gpr_platform",
],
)
@ -3130,7 +3201,10 @@ grpc_cc_library(
hdrs = [
"service_config/service_config_parser.h",
],
external_deps = ["absl/strings"],
external_deps = [
"absl/log:log",
"absl/strings",
],
language = "c++",
deps = [
"channel_args",
@ -3159,6 +3233,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/meta:type_traits",
"absl/strings",
"absl/strings:str_format",
@ -3334,6 +3409,7 @@ grpc_cc_library(
"client_channel/retry_service_config.h",
],
external_deps = [
"absl/log:log",
"absl/strings",
"absl/types:optional",
],
@ -3384,6 +3460,7 @@ grpc_cc_library(
"client_channel/backup_poller.h",
],
external_deps = [
"absl/log:log",
"absl/status",
],
language = "c++",
@ -3407,6 +3484,7 @@ grpc_cc_library(
"service_config/service_config_channel_arg_filter.cc",
],
external_deps = [
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/types:optional",
@ -3493,6 +3571,7 @@ grpc_cc_library(
hdrs = ["load_balancing/lb_policy_registry.h"],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -3603,6 +3682,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -3742,6 +3822,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/strings",
],
deps = [
@ -3789,6 +3870,7 @@ grpc_cc_library(
"lib/security/authorization/grpc_server_authz_filter.h",
],
external_deps = [
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -3831,6 +3913,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/container:flat_hash_map",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -3864,6 +3947,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -3944,6 +4028,9 @@ grpc_cc_library(
hdrs = [
"tsi/local_transport_security.h",
],
external_deps = [
"absl/log:log",
],
language = "c++",
deps = [
"//:event_engine_base_hdrs",
@ -3965,6 +4052,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -4012,6 +4100,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/strings",
"absl/strings:str_format",
@ -4057,6 +4146,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status:statusor",
"absl/strings",
"absl/types:optional",
@ -4139,6 +4229,7 @@ grpc_cc_library(
"absl/container:inlined_vector",
"absl/functional:bind_front",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -4225,6 +4316,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -4287,6 +4379,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -4333,6 +4426,7 @@ grpc_cc_library(
"lib/http/httpcli_ssl_credentials.h",
],
external_deps = [
"absl/log:log",
"absl/status",
"absl/strings",
"absl/types:optional",
@ -4407,6 +4501,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -4557,6 +4652,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/meta:type_traits",
"absl/random",
"absl/status",
@ -4638,6 +4734,7 @@ grpc_cc_library(
"ext/filters/message_size/message_size_filter.h",
],
external_deps = [
"absl/log:log",
"absl/status:statusor",
"absl/strings",
"absl/strings:str_format",
@ -4686,6 +4783,7 @@ grpc_cc_library(
],
external_deps = [
"absl/base:core_headers",
"absl/log:log",
"absl/meta:type_traits",
"absl/random",
"absl/status",
@ -4825,6 +4923,7 @@ grpc_cc_library(
"absl/container:inlined_vector",
"absl/functional:function_ref",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -4942,6 +5041,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/hash",
"absl/log:check",
"absl/log:log",
"absl/random",
"absl/status",
"absl/status:statusor",
@ -5076,6 +5176,7 @@ grpc_cc_library(
"absl/cleanup",
"absl/functional:bind_front",
"absl/log:check",
"absl/log:log",
"absl/memory",
"absl/random",
"absl/status",
@ -5260,6 +5361,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -5338,6 +5440,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -5398,6 +5501,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -5448,6 +5552,7 @@ grpc_cc_library(
"load_balancing/xds/xds_cluster_manager.cc",
],
external_deps = [
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -5491,6 +5596,7 @@ grpc_cc_library(
"load_balancing/xds/xds_wrr_locality.cc",
],
external_deps = [
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -5560,6 +5666,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -5607,6 +5714,7 @@ grpc_cc_library(
external_deps = [
"absl/functional:function_ref",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/types:optional",
@ -5644,6 +5752,7 @@ grpc_cc_library(
external_deps = [
"absl/algorithm:container",
"absl/log:check",
"absl/log:log",
"absl/random",
"absl/status",
"absl/status:statusor",
@ -5730,7 +5839,10 @@ grpc_cc_library(
hdrs = [
"lib/transport/connectivity_state.h",
],
external_deps = ["absl/status"],
external_deps = [
"absl/log:log",
"absl/status",
],
deps = [
"closure",
"error",
@ -5765,6 +5877,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/container:inlined_vector",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -5815,6 +5928,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/meta:type_traits",
"absl/random",
"absl/status",
@ -5868,6 +5982,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/meta:type_traits",
"absl/random",
"absl/status",
@ -5938,6 +6053,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/meta:type_traits",
"absl/random",
"absl/status",
@ -5987,6 +6103,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -6035,6 +6152,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/meta:type_traits",
"absl/random",
"absl/status",
@ -6084,6 +6202,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/functional:function_ref",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -6145,6 +6264,7 @@ grpc_cc_library(
],
external_deps = [
"absl/container:inlined_vector",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -6189,6 +6309,7 @@ grpc_cc_library(
"ext/filters/backend_metrics/backend_metric_filter.h",
],
external_deps = [
"absl/log:log",
"absl/status:statusor",
"absl/strings",
"absl/types:optional",
@ -6229,6 +6350,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -6293,6 +6415,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/cleanup",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -6334,7 +6457,10 @@ grpc_cc_library(
hdrs = [
"resolver/dns/dns_resolver_plugin.h",
],
external_deps = ["absl/strings"],
external_deps = [
"absl/log:log",
"absl/strings",
],
language = "c++",
deps = [
"experiments",
@ -6358,6 +6484,7 @@ grpc_cc_library(
],
external_deps = [
"absl/functional:bind_front",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -6391,6 +6518,7 @@ grpc_cc_library(
"resolver/sockaddr/sockaddr_resolver.cc",
],
external_deps = [
"absl/log:log",
"absl/status:statusor",
"absl/strings",
],
@ -6415,6 +6543,7 @@ grpc_cc_library(
"resolver/binder/binder_resolver.cc",
],
external_deps = [
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -6476,6 +6605,7 @@ grpc_cc_library(
"absl/container:flat_hash_map",
"absl/container:flat_hash_set",
"absl/log:check",
"absl/log:log",
"absl/strings",
],
language = "c++",
@ -6499,6 +6629,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/meta:type_traits",
"absl/random",
"absl/status",
@ -6560,6 +6691,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status:statusor",
"absl/strings",
"absl/types:optional",
@ -6627,6 +6759,7 @@ grpc_cc_library(
external_deps = [
"absl/functional:function_ref",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/strings",
"absl/strings:str_format",
@ -6821,6 +6954,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings:str_format",
@ -6878,6 +7012,7 @@ grpc_cc_library(
external_deps = [
"absl/base:core_headers",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -6892,6 +7027,8 @@ grpc_cc_library(
"connection_quota",
"error",
"error_utils",
"event_engine_extensions",
"event_engine_query_extensions",
"grpc_insecure_credentials",
"handshaker_registry",
"iomgr_fwd",
@ -6937,6 +7074,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -6954,6 +7092,7 @@ grpc_cc_library(
"experiments",
"iomgr_fwd",
"metadata_batch",
"resource_quota",
"slice",
"slice_buffer",
"status_helper",
@ -7062,6 +7201,7 @@ grpc_cc_library(
external_deps = [
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/strings",
@ -7115,6 +7255,7 @@ grpc_cc_library(
"ext/filters/logging/logging_filter.h",
],
external_deps = [
"absl/log:log",
"absl/numeric:int128",
"absl/random",
"absl/random:distributions",
@ -7193,7 +7334,10 @@ grpc_cc_library(
hdrs = [
"ext/transport/chaotic_good/chaotic_good_transport.h",
],
external_deps = ["absl/random"],
external_deps = [
"absl/log:log",
"absl/random",
],
language = "c++",
deps = [
"chaotic_good_frame",
@ -7222,6 +7366,7 @@ grpc_cc_library(
"absl/base:core_headers",
"absl/container:flat_hash_map",
"absl/log:check",
"absl/log:log",
"absl/random",
"absl/random:bit_gen_ref",
"absl/status",
@ -7280,6 +7425,7 @@ grpc_cc_library(
"absl/container:flat_hash_map",
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/random",
"absl/random:bit_gen_ref",
"absl/status",
@ -7365,6 +7511,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
],
deps = [
"call_final_info",
@ -7475,6 +7622,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
],
deps = [
"1999",
@ -7612,6 +7760,7 @@ grpc_cc_library(
external_deps = [
"absl/container:flat_hash_map",
"absl/log:check",
"absl/log:log",
"absl/random",
"absl/random:bit_gen_ref",
"absl/status",
@ -7677,6 +7826,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"absl/random",
"absl/random:bit_gen_ref",
"absl/status",

@ -539,11 +539,11 @@ void RegisterLoggingFilter(LoggingSink* sink) {
g_logging_sink = sink;
CoreConfiguration::RegisterBuilder([](CoreConfiguration::Builder* builder) {
builder->channel_init()
->RegisterFilter<ServerLoggingFilter>(GRPC_SERVER_CHANNEL)
->RegisterV2Filter<ServerLoggingFilter>(GRPC_SERVER_CHANNEL)
// TODO(yashykt) : Figure out a good place to place this channel arg
.IfChannelArg("grpc.experimental.enable_observability", true);
builder->channel_init()
->RegisterFilter<ClientLoggingFilter>(GRPC_CLIENT_CHANNEL)
->RegisterV2Filter<ClientLoggingFilter>(GRPC_CLIENT_CHANNEL)
// TODO(yashykt) : Figure out a good place to place this channel arg
.IfChannelArg("grpc.experimental.enable_observability", true);
});

@ -160,7 +160,7 @@ class BinderServerListener : public Server::ListenerInterface {
on_destroy_done_ = on_destroy_done;
}
void Orphan() override { delete this; }
void Orphan() override { Unref(); }
~BinderServerListener() override {
ExecCtx::Get()->Flush();
@ -240,9 +240,8 @@ bool AddBinderPort(const std::string& addr, grpc_server* server,
}
std::string conn_id = addr.substr(kBinderUriScheme.size());
Server* core_server = Server::FromC(server);
core_server->AddListener(
OrphanablePtr<Server::ListenerInterface>(new BinderServerListener(
core_server, conn_id, std::move(factory), security_policy)));
core_server->AddListener(MakeOrphanable<BinderServerListener>(
core_server, conn_id, std::move(factory), security_policy));
return true;
}

@ -24,6 +24,7 @@
#include <utility>
#include "absl/log/check.h"
#include "absl/log/log.h"
#include "absl/memory/memory.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/substitute.h"
@ -141,7 +142,7 @@ static void AssignMetadata(grpc_metadata_batch* mb,
static void cancel_stream_locked(grpc_binder_transport* transport,
grpc_binder_stream* stream,
grpc_error_handle error) {
gpr_log(GPR_INFO, "cancel_stream_locked");
LOG(INFO) << "cancel_stream_locked";
if (!stream->is_closed) {
CHECK(stream->cancel_self_error.ok());
stream->is_closed = true;
@ -200,7 +201,7 @@ static void recv_initial_metadata_locked(void* arg,
CHECK(stream->recv_initial_metadata);
CHECK(stream->recv_initial_metadata_ready);
if (!args->initial_metadata.ok()) {
gpr_log(GPR_ERROR, "Failed to parse initial metadata");
LOG(ERROR) << "Failed to parse initial metadata";
return absl_status_to_grpc_error(args->initial_metadata.status());
}
if (!stream->is_client) {
@ -237,11 +238,11 @@ static void recv_message_locked(void* arg, grpc_error_handle /*error*/) {
CHECK(stream->recv_message);
CHECK(stream->recv_message_ready);
if (!args->message.ok()) {
gpr_log(GPR_ERROR, "Failed to receive message");
LOG(ERROR) << "Failed to receive message";
if (args->message.status().message() ==
grpc_binder::TransportStreamReceiver::
kGrpcBinderTransportCancelledGracefully) {
gpr_log(GPR_ERROR, "message cancelled gracefully");
LOG(ERROR) << "message cancelled gracefully";
// Cancelled because we've already received trailing metadata.
// It's not an error in this case.
return absl::OkStatus();
@ -281,13 +282,13 @@ static void recv_trailing_metadata_locked(void* arg,
CHECK(stream->recv_trailing_metadata);
CHECK(stream->recv_trailing_metadata_finished);
if (!args->trailing_metadata.ok()) {
gpr_log(GPR_ERROR, "Failed to receive trailing metadata");
LOG(ERROR) << "Failed to receive trailing metadata";
return absl_status_to_grpc_error(args->trailing_metadata.status());
}
if (!stream->is_client) {
// Client will not send non-empty trailing metadata.
if (!args->trailing_metadata.value().empty()) {
gpr_log(GPR_ERROR, "Server receives non-empty trailing metadata.");
LOG(ERROR) << "Server receives non-empty trailing metadata.";
return absl::CancelledError();
}
} else {
@ -371,7 +372,7 @@ class MetadataEncoder {
static void accept_stream_locked(void* gt, grpc_error_handle /*error*/) {
grpc_binder_transport* transport = static_cast<grpc_binder_transport*>(gt);
if (transport->accept_stream_fn) {
gpr_log(GPR_INFO, "Accepting a stream");
LOG(INFO) << "Accepting a stream";
// must pass in a non-null value.
(*transport->accept_stream_fn)(transport->accept_stream_user_data,
transport, transport);
@ -449,7 +450,7 @@ static void perform_stream_op_locked(void* stream_op,
std::make_unique<grpc_binder::Transaction>(tx_code, transport->is_client);
if (op->send_initial_metadata) {
gpr_log(GPR_INFO, "send_initial_metadata");
LOG(INFO) << "send_initial_metadata";
grpc_binder::Metadata init_md;
auto batch = op->payload->send_initial_metadata.send_initial_metadata;
@ -459,12 +460,12 @@ static void perform_stream_op_locked(void* stream_op,
tx->SetPrefix(init_md);
}
if (op->send_message) {
gpr_log(GPR_INFO, "send_message");
LOG(INFO) << "send_message";
tx->SetData(op->payload->send_message.send_message->JoinIntoString());
}
if (op->send_trailing_metadata) {
gpr_log(GPR_INFO, "send_trailing_metadata");
LOG(INFO) << "send_trailing_metadata";
auto batch = op->payload->send_trailing_metadata.send_trailing_metadata;
grpc_binder::Metadata trailing_metadata;
@ -477,7 +478,7 @@ static void perform_stream_op_locked(void* stream_op,
tx->SetSuffix(trailing_metadata);
}
if (op->recv_initial_metadata) {
gpr_log(GPR_INFO, "recv_initial_metadata");
LOG(INFO) << "recv_initial_metadata";
stream->recv_initial_metadata_ready =
op->payload->recv_initial_metadata.recv_initial_metadata_ready;
stream->recv_initial_metadata =
@ -500,7 +501,7 @@ static void perform_stream_op_locked(void* stream_op,
});
}
if (op->recv_message) {
gpr_log(GPR_INFO, "recv_message");
LOG(INFO) << "recv_message";
stream->recv_message_ready = op->payload->recv_message.recv_message_ready;
stream->recv_message = op->payload->recv_message.recv_message;
stream->call_failed_before_recv_message =
@ -523,7 +524,7 @@ static void perform_stream_op_locked(void* stream_op,
});
}
if (op->recv_trailing_metadata) {
gpr_log(GPR_INFO, "recv_trailing_metadata");
LOG(INFO) << "recv_trailing_metadata";
stream->recv_trailing_metadata_finished =
op->payload->recv_trailing_metadata.recv_trailing_metadata_ready;
stream->recv_trailing_metadata =
@ -571,7 +572,7 @@ static void perform_stream_op_locked(void* stream_op,
if (op->on_complete != nullptr) {
grpc_core::ExecCtx::Run(DEBUG_LOCATION, op->on_complete,
absl_status_to_grpc_error(status));
gpr_log(GPR_INFO, "on_complete closure scheduled");
LOG(INFO) << "on_complete closure scheduled";
}
GRPC_BINDER_STREAM_UNREF(stream, "perform_stream_op");
}

@ -26,6 +26,7 @@
#include "absl/functional/any_invocable.h"
#include "absl/log/check.h"
#include "absl/log/log.h"
#include "absl/memory/memory.h"
#include "absl/status/statusor.h"
@ -136,9 +137,9 @@ void WireReaderImpl::SendSetupTransport(Binder* binder) {
std::unique_ptr<Binder> WireReaderImpl::RecvSetupTransport() {
// TODO(b/191941760): avoid blocking, handle wire_writer_noti lifetime
// better
gpr_log(GPR_DEBUG, "start waiting for noti");
VLOG(2) << "start waiting for noti";
connection_noti_.WaitForNotification();
gpr_log(GPR_DEBUG, "end waiting for noti");
VLOG(2) << "end waiting for noti";
return std::move(other_end_binder_);
}
@ -153,8 +154,8 @@ absl::Status WireReaderImpl::ProcessTransaction(transaction_code_t code,
BinderTransportTxCode::SETUP_TRANSPORT) &&
code <= static_cast<transaction_code_t>(
BinderTransportTxCode::PING_RESPONSE))) {
gpr_log(GPR_INFO,
"Received unknown control message. Shutdown transport gracefully.");
LOG(INFO)
<< "Received unknown control message. Shutdown transport gracefully.";
// TODO(waynetu): Shutdown transport gracefully.
return absl::OkStatus();
}
@ -210,8 +211,8 @@ absl::Status WireReaderImpl::ProcessTransaction(transaction_code_t code,
break;
}
case BinderTransportTxCode::SHUTDOWN_TRANSPORT: {
gpr_log(GPR_ERROR,
"Received SHUTDOWN_TRANSPORT request but not implemented yet.");
LOG(ERROR)
<< "Received SHUTDOWN_TRANSPORT request but not implemented yet.";
return absl::UnimplementedError("SHUTDOWN_TRANSPORT");
}
case BinderTransportTxCode::ACKNOWLEDGE_BYTES: {
@ -286,16 +287,16 @@ absl::Status WireReaderImpl::ProcessStreamingTransaction(
tx_process_result.ToString().c_str());
// Something went wrong when receiving transaction. Cancel failed requests.
if (cancellation_flags & kFlagPrefix) {
gpr_log(GPR_INFO, "cancelling initial metadata");
LOG(INFO) << "cancelling initial metadata";
transport_stream_receiver_->NotifyRecvInitialMetadata(code,
tx_process_result);
}
if (cancellation_flags & kFlagMessageData) {
gpr_log(GPR_INFO, "cancelling message data");
LOG(INFO) << "cancelling message data";
transport_stream_receiver_->NotifyRecvMessage(code, tx_process_result);
}
if (cancellation_flags & kFlagSuffix) {
gpr_log(GPR_INFO, "cancelling trailing metadata");
LOG(INFO) << "cancelling trailing metadata";
transport_stream_receiver_->NotifyRecvTrailingMetadata(
code, tx_process_result, 0);
}
@ -338,7 +339,7 @@ absl::Status WireReaderImpl::ProcessStreamingTransactionImpl(
// intended behavior.
// TODO(waynetu): What should be returned here?
if (flags == 0) {
gpr_log(GPR_INFO, "[WARNING] Receive empty transaction. Ignored.");
LOG(INFO) << "[WARNING] Receive empty transaction. Ignored.";
return absl::OkStatus();
}

@ -103,8 +103,8 @@ absl::StatusOr<int> ChaoticGoodServerListener::Bind(
str.ok() ? str->c_str() : str.status().ToString().c_str());
}
EventEngine::Listener::AcceptCallback accept_cb =
[self = Ref()](std::unique_ptr<EventEngine::Endpoint> ep,
MemoryAllocator) {
[self = RefAsSubclass<ChaoticGoodServerListener>()](
std::unique_ptr<EventEngine::Endpoint> ep, MemoryAllocator) {
ExecCtx exec_ctx;
MutexLock lock(&self->mu_);
if (self->shutdown_) return;
@ -149,7 +149,8 @@ absl::Status ChaoticGoodServerListener::StartListening() {
ChaoticGoodServerListener::ActiveConnection::ActiveConnection(
RefCountedPtr<ChaoticGoodServerListener> listener,
std::unique_ptr<EventEngine::Endpoint> endpoint)
: memory_allocator_(listener->memory_allocator_), listener_(listener) {
: memory_allocator_(listener->memory_allocator_),
listener_(std::move(listener)) {
handshaking_state_ = MakeRefCounted<HandshakingState>(Ref());
handshaking_state_->Start(std::move(endpoint));
}

@ -49,9 +49,7 @@
namespace grpc_core {
namespace chaotic_good {
class ChaoticGoodServerListener final
: public Server::ListenerInterface,
public RefCounted<ChaoticGoodServerListener> {
class ChaoticGoodServerListener final : public Server::ListenerInterface {
public:
static absl::AnyInvocable<std::string()> DefaultConnectionIDGenerator() {
return [bitgen = absl::BitGen()]() mutable {

@ -235,37 +235,27 @@ auto ChaoticGoodServerTransport::DeserializeAndPushFragmentToNewCall(
FrameHeader frame_header, BufferPair buffers,
ChaoticGoodTransport& transport) {
ClientFragmentFrame fragment_frame;
ScopedArenaPtr arena(acceptor_->CreateArena());
ScopedArenaPtr arena(call_arena_allocator_->MakeArena());
absl::Status status = transport.DeserializeFrame(
frame_header, std::move(buffers), arena.get(), fragment_frame,
FrameLimits{1024 * 1024 * 1024, aligned_bytes_ - 1});
absl::optional<CallInitiator> call_initiator;
if (status.ok()) {
auto create_call_result = acceptor_->CreateCall(
std::move(fragment_frame.headers), arena.release());
if (grpc_chaotic_good_trace.enabled()) {
gpr_log(GPR_INFO,
"CHAOTIC_GOOD: DeserializeAndPushFragmentToNewCall: "
"create_call_result=%s",
create_call_result.ok()
? "ok"
: create_call_result.status().ToString().c_str());
}
if (create_call_result.ok()) {
call_initiator.emplace(std::move(*create_call_result));
auto add_result = NewStream(frame_header.stream_id, *call_initiator);
if (add_result.ok()) {
call_initiator->SpawnGuarded(
"server-write", [this, stream_id = frame_header.stream_id,
call_initiator = *call_initiator]() {
return CallOutboundLoop(stream_id, call_initiator);
});
} else {
call_initiator.reset();
status = add_result;
}
auto call =
MakeCallPair(std::move(fragment_frame.headers), event_engine_.get(),
arena.release(), call_arena_allocator_, nullptr);
call_initiator.emplace(std::move(call.initiator));
auto add_result = NewStream(frame_header.stream_id, *call_initiator);
if (add_result.ok()) {
call_destination_->StartCall(std::move(call.handler));
call_initiator->SpawnGuarded(
"server-write", [this, stream_id = frame_header.stream_id,
call_initiator = *call_initiator]() {
return CallOutboundLoop(stream_id, call_initiator);
});
} else {
status = create_call_result.status();
call_initiator.reset();
status = add_result;
}
}
return MaybePushFragmentIntoCall(std::move(call_initiator), std::move(status),
@ -366,10 +356,13 @@ ChaoticGoodServerTransport::ChaoticGoodServerTransport(
PromiseEndpoint data_endpoint,
std::shared_ptr<grpc_event_engine::experimental::EventEngine> event_engine,
HPackParser hpack_parser, HPackCompressor hpack_encoder)
: outgoing_frames_(4),
allocator_(args.GetObject<ResourceQuota>()
->memory_quota()
->CreateMemoryAllocator("chaotic-good")) {
: call_arena_allocator_(MakeRefCounted<CallArenaAllocator>(
args.GetObject<ResourceQuota>()
->memory_quota()
->CreateMemoryAllocator("chaotic-good"),
1024)),
event_engine_(event_engine),
outgoing_frames_(4) {
auto transport = MakeRefCounted<ChaoticGoodTransport>(
std::move(control_endpoint), std::move(data_endpoint),
std::move(hpack_parser), std::move(hpack_encoder));
@ -381,20 +374,25 @@ ChaoticGoodServerTransport::ChaoticGoodServerTransport(
OnTransportActivityDone("reader"));
}
void ChaoticGoodServerTransport::SetAcceptor(Acceptor* acceptor) {
CHECK_EQ(acceptor_, nullptr);
CHECK_NE(acceptor, nullptr);
acceptor_ = acceptor;
void ChaoticGoodServerTransport::SetCallDestination(
RefCountedPtr<UnstartedCallDestination> call_destination) {
CHECK(call_destination_ == nullptr);
CHECK(call_destination != nullptr);
call_destination_ = call_destination;
got_acceptor_.Set();
}
ChaoticGoodServerTransport::~ChaoticGoodServerTransport() {
if (writer_ != nullptr) {
writer_.reset();
}
if (reader_ != nullptr) {
reader_.reset();
void ChaoticGoodServerTransport::Orphan() {
ActivityPtr writer;
ActivityPtr reader;
{
MutexLock lock(&mu_);
writer = std::move(writer_);
reader = std::move(reader_);
}
writer.reset();
reader.reset();
Unref();
}
void ChaoticGoodServerTransport::AbortWithError() {

@ -86,7 +86,6 @@ class ChaoticGoodServerTransport final : public ServerTransport {
std::shared_ptr<grpc_event_engine::experimental::EventEngine>
event_engine,
HPackParser hpack_parser, HPackCompressor hpack_encoder);
~ChaoticGoodServerTransport() override;
FilterStackTransport* filter_stack_transport() override { return nullptr; }
ClientTransport* client_transport() override { return nullptr; }
@ -96,9 +95,10 @@ class ChaoticGoodServerTransport final : public ServerTransport {
void SetPollsetSet(grpc_stream*, grpc_pollset_set*) override {}
void PerformOp(grpc_transport_op*) override;
grpc_endpoint* GetEndpoint() override { return nullptr; }
void Orphan() override { Unref(); }
void Orphan() override;
void SetAcceptor(Acceptor* acceptor) override;
void SetCallDestination(
RefCountedPtr<UnstartedCallDestination> call_destination) override;
void AbortWithError();
private:
@ -137,7 +137,10 @@ class ChaoticGoodServerTransport final : public ServerTransport {
auto PushFragmentIntoCall(CallInitiator call_initiator,
ClientFragmentFrame frame, uint32_t stream_id);
Acceptor* acceptor_ = nullptr;
RefCountedPtr<UnstartedCallDestination> call_destination_;
const RefCountedPtr<CallArenaAllocator> call_arena_allocator_;
const std::shared_ptr<grpc_event_engine::experimental::EventEngine>
event_engine_;
InterActivityLatch<void> got_acceptor_;
MpscReceiver<ServerFrame> outgoing_frames_;
// Assigned aligned bytes from setting frame.
@ -146,7 +149,6 @@ class ChaoticGoodServerTransport final : public ServerTransport {
// Map of stream incoming server frames, key is stream_id.
StreamMap stream_map_ ABSL_GUARDED_BY(mu_);
uint32_t last_seen_new_stream_id_ = 0;
grpc_event_engine::experimental::MemoryAllocator allocator_;
ActivityPtr writer_ ABSL_GUARDED_BY(mu_);
ActivityPtr reader_ ABSL_GUARDED_BY(mu_);
ConnectivityStateTracker state_tracker_ ABSL_GUARDED_BY(mu_){

@ -42,6 +42,7 @@
#include <grpc/grpc.h>
#include <grpc/grpc_posix.h>
#include <grpc/impl/channel_arg_names.h>
#include <grpc/passive_listener.h>
#include <grpc/slice_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
@ -58,6 +59,8 @@
#include "src/core/lib/config/core_configuration.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/event_engine/channel_args_endpoint_config.h"
#include "src/core/lib/event_engine/extensions/supports_fd.h"
#include "src/core/lib/event_engine/query_extensions.h"
#include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
@ -67,6 +70,7 @@
#include "src/core/lib/gprpp/unique_type_name.h"
#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/iomgr/endpoint.h"
#include "src/core/lib/iomgr/event_engine_shims/endpoint.h"
#include "src/core/lib/iomgr/iomgr_fwd.h"
#include "src/core/lib/iomgr/pollset_set.h"
#include "src/core/lib/iomgr/resolve_address.h"
@ -93,9 +97,11 @@
#endif // GPR_SUPPORT_CHANNELS_FROM_FD
namespace grpc_core {
namespace {
using ::grpc_event_engine::experimental::EventEngine;
using grpc_event_engine::experimental::ChannelArgsEndpointConfig;
using grpc_event_engine::experimental::EventEngine;
using grpc_event_engine::experimental::EventEngineSupportsFdExtension;
using grpc_event_engine::experimental::QueryExtension;
const char kUnixUriPrefix[] = "unix:";
const char kUnixAbstractUriPrefix[] = "unix-abstract:";
@ -112,14 +118,23 @@ class Chttp2ServerListener : public Server::ListenerInterface {
Server* server, const char* name, const ChannelArgs& args,
Chttp2ServerArgsModifier args_modifier);
static Chttp2ServerListener* CreateForPassiveListener(
Server* server, const ChannelArgs& args,
std::shared_ptr<experimental::PassiveListenerImpl> passive_listener);
// Do not instantiate directly. Use one of the factory methods above.
Chttp2ServerListener(Server* server, const ChannelArgs& args,
Chttp2ServerArgsModifier args_modifier);
Chttp2ServerArgsModifier args_modifier,
grpc_server_config_fetcher* config_fetcher,
std::shared_ptr<experimental::PassiveListenerImpl>
passive_listener = nullptr);
~Chttp2ServerListener() override;
void Start(Server* server,
const std::vector<grpc_pollset*>* pollsets) override;
void AcceptConnectedEndpoint(std::unique_ptr<EventEngine::Endpoint> endpoint);
channelz::ListenSocketNode* channelz_listen_socket_node() const override {
return channelz_listen_socket_.get();
}
@ -129,6 +144,8 @@ class Chttp2ServerListener : public Server::ListenerInterface {
void Orphan() override;
private:
friend class experimental::PassiveListenerImpl;
class ConfigFetcherWatcher
: public grpc_server_config_fetcher::WatcherInterface {
public:
@ -235,34 +252,8 @@ class Chttp2ServerListener : public Server::ListenerInterface {
static void DestroyListener(Server* /*server*/, void* arg,
grpc_closure* destroy_done);
// The interface required by RefCountedPtr<> has been manually implemented
// here to take a ref on tcp_server_ instead. Note that, the handshaker
// needs tcp_server_ to exist for the lifetime of the handshake since it's
// needed by acceptor. Sharing refs between the listener and tcp_server_ is
// just an optimization to avoid taking additional refs on the listener,
// since TcpServerShutdownComplete already holds a ref to the listener.
void IncrementRefCount() { grpc_tcp_server_ref(tcp_server_); }
void IncrementRefCount(const DebugLocation& /* location */,
const char* /* reason */) {
IncrementRefCount();
}
GRPC_MUST_USE_RESULT RefCountedPtr<Chttp2ServerListener> Ref() {
IncrementRefCount();
return RefCountedPtr<Chttp2ServerListener>(this);
}
GRPC_MUST_USE_RESULT RefCountedPtr<Chttp2ServerListener> Ref(
const DebugLocation& /* location */, const char* /* reason */) {
return Ref();
}
void Unref() { grpc_tcp_server_unref(tcp_server_); }
void Unref(const DebugLocation& /* location */, const char* /* reason */) {
Unref();
}
Server* const server_;
grpc_tcp_server* tcp_server_;
Server* const server_ = nullptr;
grpc_tcp_server* tcp_server_ = nullptr;
grpc_resolved_address resolved_address_;
Chttp2ServerArgsModifier const args_modifier_;
ConfigFetcherWatcher* config_fetcher_watcher_ = nullptr;
@ -285,6 +276,10 @@ class Chttp2ServerListener : public Server::ListenerInterface {
RefCountedPtr<channelz::ListenSocketNode> channelz_listen_socket_;
MemoryQuotaRefPtr memory_quota_;
ConnectionQuotaRefPtr connection_quota_;
grpc_server_config_fetcher* config_fetcher_ = nullptr;
// TODO(yashykt): consider using absl::variant<> to minimize memory usage for
// disjoint cases where different fields are used.
std::shared_ptr<experimental::PassiveListenerImpl> passive_listener_;
};
//
@ -381,13 +376,17 @@ Chttp2ServerListener::ActiveConnection::HandshakingState::HandshakingState(
handshake_mgr_(MakeRefCounted<HandshakeManager>()),
deadline_(GetConnectionDeadline(args)),
interested_parties_(grpc_pollset_set_create()) {
grpc_pollset_set_add_pollset(interested_parties_, accepting_pollset_);
if (accepting_pollset != nullptr) {
grpc_pollset_set_add_pollset(interested_parties_, accepting_pollset_);
}
CoreConfiguration::Get().handshaker_registry().AddHandshakers(
HANDSHAKER_SERVER, args, interested_parties_, handshake_mgr_.get());
}
Chttp2ServerListener::ActiveConnection::HandshakingState::~HandshakingState() {
grpc_pollset_set_del_pollset(interested_parties_, accepting_pollset_);
if (accepting_pollset_ != nullptr) {
grpc_pollset_set_del_pollset(interested_parties_, accepting_pollset_);
}
grpc_pollset_set_destroy(interested_parties_);
gpr_free(acceptor_);
}
@ -589,7 +588,11 @@ Chttp2ServerListener::ActiveConnection::ActiveConnection(
grpc_schedule_on_exec_ctx);
}
Chttp2ServerListener::ActiveConnection::~ActiveConnection() {}
Chttp2ServerListener::ActiveConnection::~ActiveConnection() {
if (listener_ != nullptr && listener_->tcp_server_ != nullptr) {
grpc_tcp_server_unref(listener_->tcp_server_);
}
}
void Chttp2ServerListener::ActiveConnection::Orphan() {
OrphanablePtr<HandshakingState> handshaking_state;
@ -637,6 +640,9 @@ void Chttp2ServerListener::ActiveConnection::Start(
const ChannelArgs& args) {
RefCountedPtr<HandshakingState> handshaking_state_ref;
listener_ = std::move(listener);
if (listener_->tcp_server_ != nullptr) {
grpc_tcp_server_ref(listener_->tcp_server_);
}
{
ReleasableMutexLock lock(&mu_);
if (shutdown_) {
@ -709,83 +715,82 @@ void Chttp2ServerListener::ActiveConnection::OnDrainGraceTimeExpiry() {
grpc_error_handle Chttp2ServerListener::Create(
Server* server, grpc_resolved_address* addr, const ChannelArgs& args,
Chttp2ServerArgsModifier args_modifier, int* port_num) {
Chttp2ServerListener* listener = nullptr;
// The bulk of this method is inside of a lambda to make cleanup
// easier without using goto.
grpc_error_handle error = [&]() {
grpc_error_handle error;
// Create Chttp2ServerListener.
listener = new Chttp2ServerListener(server, args, args_modifier);
error = grpc_tcp_server_create(
&listener->tcp_server_shutdown_complete_,
grpc_event_engine::experimental::ChannelArgsEndpointConfig(args),
OnAccept, listener, &listener->tcp_server_);
// Create Chttp2ServerListener.
OrphanablePtr<Chttp2ServerListener> listener =
MakeOrphanable<Chttp2ServerListener>(server, args, args_modifier,
server->config_fetcher());
// The tcp_server will be unreffed when the listener is orphaned, which could
// be at the end of this function if the listener was not added to the
// server's set of listeners.
grpc_error_handle error = grpc_tcp_server_create(
&listener->tcp_server_shutdown_complete_, ChannelArgsEndpointConfig(args),
OnAccept, listener.get(), &listener->tcp_server_);
if (!error.ok()) return error;
if (listener->config_fetcher_ != nullptr) {
listener->resolved_address_ = *addr;
// TODO(yashykt): Consider binding so as to be able to return the port
// number.
} else {
error = grpc_tcp_server_add_port(listener->tcp_server_, addr, port_num);
if (!error.ok()) return error;
if (server->config_fetcher() != nullptr) {
listener->resolved_address_ = *addr;
// TODO(yashykt): Consider binding so as to be able to return the port
// number.
} else {
error = grpc_tcp_server_add_port(listener->tcp_server_, addr, port_num);
if (!error.ok()) return error;
}
// Create channelz node.
if (args.GetBool(GRPC_ARG_ENABLE_CHANNELZ)
.value_or(GRPC_ENABLE_CHANNELZ_DEFAULT)) {
auto string_address = grpc_sockaddr_to_uri(addr);
if (!string_address.ok()) {
return GRPC_ERROR_CREATE(string_address.status().ToString());
}
listener->channelz_listen_socket_ =
MakeRefCounted<channelz::ListenSocketNode>(
*string_address,
absl::StrCat("chttp2 listener ", *string_address));
}
// Register with the server only upon success
server->AddListener(OrphanablePtr<Server::ListenerInterface>(listener));
return absl::OkStatus();
}();
if (!error.ok()) {
if (listener != nullptr) {
if (listener->tcp_server_ != nullptr) {
// listener is deleted when tcp_server_ is shutdown.
grpc_tcp_server_unref(listener->tcp_server_);
} else {
delete listener;
}
}
// Create channelz node.
if (args.GetBool(GRPC_ARG_ENABLE_CHANNELZ)
.value_or(GRPC_ENABLE_CHANNELZ_DEFAULT)) {
auto string_address = grpc_sockaddr_to_uri(addr);
if (!string_address.ok()) {
return GRPC_ERROR_CREATE(string_address.status().ToString());
}
listener->channelz_listen_socket_ =
MakeRefCounted<channelz::ListenSocketNode>(
*string_address, absl::StrCat("chttp2 listener ", *string_address));
}
return error;
// Register with the server only upon success
server->AddListener(std::move(listener));
return absl::OkStatus();
}
grpc_error_handle Chttp2ServerListener::CreateWithAcceptor(
Server* server, const char* name, const ChannelArgs& args,
Chttp2ServerArgsModifier args_modifier) {
Chttp2ServerListener* listener =
new Chttp2ServerListener(server, args, args_modifier);
auto listener = MakeOrphanable<Chttp2ServerListener>(
server, args, args_modifier, server->config_fetcher());
grpc_error_handle error = grpc_tcp_server_create(
&listener->tcp_server_shutdown_complete_,
grpc_event_engine::experimental::ChannelArgsEndpointConfig(args),
OnAccept, listener, &listener->tcp_server_);
if (!error.ok()) {
delete listener;
return error;
}
&listener->tcp_server_shutdown_complete_, ChannelArgsEndpointConfig(args),
OnAccept, listener.get(), &listener->tcp_server_);
if (!error.ok()) return error;
// TODO(yangg) channelz
TcpServerFdHandler** arg_val = args.GetPointer<TcpServerFdHandler*>(name);
*arg_val = grpc_tcp_server_create_fd_handler(listener->tcp_server_);
server->AddListener(OrphanablePtr<Server::ListenerInterface>(listener));
server->AddListener(std::move(listener));
return absl::OkStatus();
}
Chttp2ServerListener* Chttp2ServerListener::CreateForPassiveListener(
Server* server, const ChannelArgs& args,
std::shared_ptr<experimental::PassiveListenerImpl> passive_listener) {
// TODO(hork): figure out how to handle channelz in this case
auto listener = MakeOrphanable<Chttp2ServerListener>(
server, args, /*args_modifier=*/
[](const ChannelArgs& args, grpc_error_handle*) { return args; }, nullptr,
std::move(passive_listener));
auto listener_ptr = listener.get();
server->AddListener(std::move(listener));
return listener_ptr;
}
Chttp2ServerListener::Chttp2ServerListener(
Server* server, const ChannelArgs& args,
Chttp2ServerArgsModifier args_modifier)
Chttp2ServerArgsModifier args_modifier,
grpc_server_config_fetcher* config_fetcher,
std::shared_ptr<experimental::PassiveListenerImpl> passive_listener)
: server_(server),
args_modifier_(args_modifier),
args_(args),
memory_quota_(args.GetObject<ResourceQuota>()->memory_quota()),
connection_quota_(MakeRefCounted<ConnectionQuota>()) {
connection_quota_(MakeRefCounted<ConnectionQuota>()),
config_fetcher_(config_fetcher),
passive_listener_(std::move(passive_listener)) {
auto max_allowed_incoming_connections =
args.GetInt(GRPC_ARG_MAX_ALLOWED_INCOMING_CONNECTIONS);
if (max_allowed_incoming_connections.has_value()) {
@ -800,6 +805,9 @@ Chttp2ServerListener::~Chttp2ServerListener() {
// Flush queued work before destroying handshaker factory, since that
// may do a synchronous unref.
ExecCtx::Get()->Flush();
if (passive_listener_ != nullptr) {
passive_listener_->ListenerDestroyed();
}
if (on_destroy_done_ != nullptr) {
ExecCtx::Run(DEBUG_LOCATION, on_destroy_done_, absl::OkStatus());
ExecCtx::Get()->Flush();
@ -809,10 +817,11 @@ Chttp2ServerListener::~Chttp2ServerListener() {
// Server callback: start listening on our ports
void Chttp2ServerListener::Start(
Server* /*server*/, const std::vector<grpc_pollset*>* /* pollsets */) {
if (server_->config_fetcher() != nullptr) {
auto watcher = std::make_unique<ConfigFetcherWatcher>(Ref());
if (config_fetcher_ != nullptr) {
auto watcher = std::make_unique<ConfigFetcherWatcher>(
RefAsSubclass<Chttp2ServerListener>());
config_fetcher_watcher_ = watcher.get();
server_->config_fetcher()->StartWatch(
config_fetcher_->StartWatch(
grpc_sockaddr_to_string(&resolved_address_, false).value(),
std::move(watcher));
} else {
@ -826,7 +835,9 @@ void Chttp2ServerListener::Start(
}
void Chttp2ServerListener::StartListening() {
grpc_tcp_server_start(tcp_server_, &server_->pollsets());
if (tcp_server_ != nullptr) {
grpc_tcp_server_start(tcp_server_, &server_->pollsets());
}
}
void Chttp2ServerListener::SetOnDestroyDone(grpc_closure* on_destroy_done) {
@ -834,6 +845,12 @@ void Chttp2ServerListener::SetOnDestroyDone(grpc_closure* on_destroy_done) {
on_destroy_done_ = on_destroy_done;
}
void Chttp2ServerListener::AcceptConnectedEndpoint(
std::unique_ptr<EventEngine::Endpoint> endpoint) {
OnAccept(this, grpc_event_engine_endpoint_create(std::move(endpoint)),
/*accepting_pollset=*/nullptr, /*acceptor=*/nullptr);
}
void Chttp2ServerListener::OnAccept(void* arg, grpc_endpoint* tcp,
grpc_pollset* accepting_pollset,
grpc_tcp_server_acceptor* acceptor) {
@ -858,7 +875,7 @@ void Chttp2ServerListener::OnAccept(void* arg, grpc_endpoint* tcp,
endpoint_cleanup(error);
return;
}
if (self->server_->config_fetcher() != nullptr) {
if (self->config_fetcher_ != nullptr) {
if (connection_manager == nullptr) {
grpc_error_handle error = GRPC_ERROR_CREATE(
"No ConnectionManager configured. Closing connection.");
@ -899,7 +916,7 @@ void Chttp2ServerListener::OnAccept(void* arg, grpc_endpoint* tcp,
// heap-use-after-free issues where `Ref()` is invoked when the ref of
// tcp_server_ has already reached 0. (Ref() implementation of
// Chttp2ServerListener is grpc_tcp_server_ref().)
listener_ref = self->Ref();
listener_ref = self->RefAsSubclass<Chttp2ServerListener>();
self->connections_.emplace(connection.get(), std::move(connection));
}
}
@ -914,7 +931,7 @@ void Chttp2ServerListener::TcpServerShutdownComplete(
void* arg, grpc_error_handle /*error*/) {
Chttp2ServerListener* self = static_cast<Chttp2ServerListener*>(arg);
self->channelz_listen_socket_.reset();
delete self;
self->Unref();
}
// Server callback: destroy the tcp listener (so we don't generate further
@ -923,7 +940,8 @@ void Chttp2ServerListener::Orphan() {
// Cancel the watch before shutting down so as to avoid holding a ref to the
// listener in the watcher.
if (config_fetcher_watcher_ != nullptr) {
server_->config_fetcher()->CancelWatch(config_fetcher_watcher_);
CHECK_NE(config_fetcher_, nullptr);
config_fetcher_->CancelWatch(config_fetcher_watcher_);
}
std::map<ActiveConnection*, OrphanablePtr<ActiveConnection>> connections;
grpc_tcp_server* tcp_server;
@ -941,12 +959,14 @@ void Chttp2ServerListener::Orphan() {
}
tcp_server = tcp_server_;
}
grpc_tcp_server_shutdown_listeners(tcp_server);
grpc_tcp_server_unref(tcp_server);
if (tcp_server != nullptr) {
grpc_tcp_server_shutdown_listeners(tcp_server);
grpc_tcp_server_unref(tcp_server);
} else {
Unref();
}
}
} // namespace
//
// Chttp2ServerAddPort()
//
@ -1047,6 +1067,50 @@ ChannelArgs ModifyArgsForConnection(const ChannelArgs& args,
}
} // namespace
namespace experimental {
absl::Status PassiveListenerImpl::AcceptConnectedEndpoint(
std::unique_ptr<EventEngine::Endpoint> endpoint) {
CHECK_NE(server_.get(), nullptr);
RefCountedPtr<Chttp2ServerListener> listener;
{
MutexLock lock(&mu_);
if (listener_ != nullptr) {
listener =
listener_->RefIfNonZero().TakeAsSubclass<Chttp2ServerListener>();
}
}
if (listener == nullptr) {
return absl::UnavailableError("passive listener already shut down");
}
ExecCtx exec_ctx;
listener->AcceptConnectedEndpoint(std::move(endpoint));
return absl::OkStatus();
}
absl::Status PassiveListenerImpl::AcceptConnectedFd(int fd) {
CHECK_NE(server_.get(), nullptr);
ExecCtx exec_ctx;
auto& args = server_->channel_args();
auto* supports_fd = QueryExtension<EventEngineSupportsFdExtension>(
/*engine=*/args.GetObjectRef<EventEngine>().get());
if (supports_fd == nullptr) {
return absl::UnimplementedError(
"The server's EventEngine does not support adding endpoints from "
"connected file descriptors.");
}
auto endpoint =
supports_fd->CreateEndpointFromFd(fd, ChannelArgsEndpointConfig(args));
return AcceptConnectedEndpoint(std::move(endpoint));
}
void PassiveListenerImpl::ListenerDestroyed() {
MutexLock lock(&mu_);
listener_ = nullptr;
}
} // namespace experimental
} // namespace grpc_core
int grpc_server_add_http2_port(grpc_server* server, const char* addr,
@ -1144,3 +1208,31 @@ void grpc_server_add_channel_from_fd(grpc_server* /* server */, int /* fd */,
}
#endif // GPR_SUPPORT_CHANNELS_FROM_FD
absl::Status grpc_server_add_passive_listener(
grpc_core::Server* server, grpc_server_credentials* credentials,
std::shared_ptr<grpc_core::experimental::PassiveListenerImpl>
passive_listener) {
grpc_core::ExecCtx exec_ctx;
GRPC_API_TRACE("grpc_server_add_passive_listener(server=%p, credentials=%p)",
2, (server, credentials));
// Create security context.
if (credentials == nullptr) {
return absl::UnavailableError(
"No credentials specified for passive listener");
}
auto sc = credentials->create_security_connector(grpc_core::ChannelArgs());
if (sc == nullptr) {
return absl::UnavailableError(
absl::StrCat("Unable to create secure server with credentials of type ",
credentials->type().name()));
}
auto args = server->channel_args()
.SetObject(credentials->Ref())
.SetObject(std::move(sc));
passive_listener->listener_ =
grpc_core::Chttp2ServerListener::CreateForPassiveListener(
server, args, passive_listener);
passive_listener->server_ = server->Ref();
return absl::OkStatus();
}

@ -21,6 +21,7 @@
#include <functional>
#include <grpc/passive_listener.h>
#include <grpc/support/port_platform.h>
#include "src/core/lib/channel/channel_args.h"
@ -42,6 +43,38 @@ grpc_error_handle Chttp2ServerAddPort(
Server* server, const char* addr, const ChannelArgs& args,
Chttp2ServerArgsModifier connection_args_modifier, int* port_num);
class Chttp2ServerListener;
namespace experimental {
// An implementation of the public C++ passive listener interface.
// The server builder holds a weak_ptr to one of these objects, and the
// application owns the instance.
class PassiveListenerImpl final : public PassiveListener {
public:
absl::Status AcceptConnectedEndpoint(
std::unique_ptr<grpc_event_engine::experimental::EventEngine::Endpoint>
endpoint) override ABSL_LOCKS_EXCLUDED(mu_);
absl::Status AcceptConnectedFd(GRPC_UNUSED int fd) override
ABSL_LOCKS_EXCLUDED(mu_);
void ListenerDestroyed() ABSL_LOCKS_EXCLUDED(mu_);
private:
// note: the grpc_core::Server redundant namespace qualification is
// required for older gcc versions.
friend absl::Status(::grpc_server_add_passive_listener)(
grpc_core::Server* server, grpc_server_credentials* credentials,
std::shared_ptr<grpc_core::experimental::PassiveListenerImpl>
passive_listener);
Mutex mu_;
// Data members will be populated when initialized.
RefCountedPtr<Server> server_;
Chttp2ServerListener* listener_;
};
} // namespace experimental
} // namespace grpc_core
#endif // GRPC_SRC_CORE_EXT_TRANSPORT_CHTTP2_SERVER_CHTTP2_SERVER_H

@ -35,6 +35,7 @@
#include "absl/container/flat_hash_map.h"
#include "absl/hash/hash.h"
#include "absl/log/check.h"
#include "absl/log/log.h"
#include "absl/meta/type_traits.h"
#include "absl/random/random.h"
#include "absl/status/status.h"
@ -1324,7 +1325,7 @@ static bool contains_non_ok_status(grpc_metadata_batch* batch) {
static void log_metadata(const grpc_metadata_batch* md_batch, uint32_t id,
bool is_client, bool is_initial) {
gpr_log(GPR_INFO, "--metadata--");
LOG(INFO) << "--metadata--";
const std::string prefix = absl::StrCat(
"HTTP:", id, is_initial ? ":HDR" : ":TRL", is_client ? ":CLI:" : ":SVR:");
md_batch->Log([&prefix](absl::string_view key, absl::string_view value) {

@ -41,6 +41,7 @@ grpc_cc_library(
],
external_deps = [
"absl/log:check",
"absl/log:log",
"cronet_c_for_grpc",
],
language = "c++",

@ -28,6 +28,7 @@
#include "src/core/lib/gprpp/crash.h"
#include "src/core/lib/promise/promise.h"
#include "src/core/lib/promise/try_seq.h"
#include "src/core/lib/resource_quota/resource_quota.h"
#include "src/core/lib/surface/channel_create.h"
#include "src/core/lib/transport/transport.h"
#include "src/core/server/server.h"
@ -39,8 +40,18 @@ class InprocClientTransport;
class InprocServerTransport final : public ServerTransport {
public:
void SetAcceptor(Acceptor* acceptor) override {
acceptor_ = acceptor;
explicit InprocServerTransport(const ChannelArgs& args)
: event_engine_(
args.GetObjectRef<grpc_event_engine::experimental::EventEngine>()),
call_arena_allocator_(MakeRefCounted<CallArenaAllocator>(
args.GetObject<ResourceQuota>()
->memory_quota()
->CreateMemoryAllocator("inproc_server"),
1024)) {}
void SetCallDestination(
RefCountedPtr<UnstartedCallDestination> unstarted_call_handler) override {
unstarted_call_handler_ = unstarted_call_handler;
ConnectionState expect = ConnectionState::kInitial;
state_.compare_exchange_strong(expect, ConnectionState::kReady,
std::memory_order_acq_rel,
@ -95,7 +106,11 @@ class InprocServerTransport final : public ServerTransport {
case ConnectionState::kReady:
break;
}
return acceptor_->CreateCall(std::move(md), acceptor_->CreateArena());
auto* arena = call_arena_allocator_->MakeArena();
auto server_call = MakeCallPair(std::move(md), event_engine_.get(), arena,
call_arena_allocator_, nullptr);
unstarted_call_handler_->StartCall(std::move(server_call.handler));
return std::move(server_call.initiator);
}
OrphanablePtr<InprocClientTransport> MakeClientTransport();
@ -105,11 +120,14 @@ class InprocServerTransport final : public ServerTransport {
std::atomic<ConnectionState> state_{ConnectionState::kInitial};
std::atomic<bool> disconnecting_{false};
Acceptor* acceptor_;
RefCountedPtr<UnstartedCallDestination> unstarted_call_handler_;
absl::Status disconnect_error_;
Mutex state_tracker_mu_;
ConnectivityStateTracker state_tracker_ ABSL_GUARDED_BY(state_tracker_mu_){
"inproc_server_transport", GRPC_CHANNEL_CONNECTING};
const std::shared_ptr<grpc_event_engine::experimental::EventEngine>
event_engine_;
const RefCountedPtr<CallArenaAllocator> call_arena_allocator_;
};
class InprocClientTransport final : public ClientTransport {
@ -118,16 +136,19 @@ class InprocClientTransport final : public ClientTransport {
RefCountedPtr<InprocServerTransport> server_transport)
: server_transport_(std::move(server_transport)) {}
void StartCall(CallHandler call_handler) override {
call_handler.SpawnGuarded(
void StartCall(CallHandler child_call_handler) override {
child_call_handler.SpawnGuarded(
"pull_initial_metadata",
TrySeq(call_handler.PullClientInitialMetadata(),
TrySeq(child_call_handler.PullClientInitialMetadata(),
[server_transport = server_transport_,
call_handler](ClientMetadataHandle md) {
auto call_initiator =
child_call_handler](ClientMetadataHandle md) {
auto server_call_initiator =
server_transport->AcceptCall(std::move(md));
if (!call_initiator.ok()) return call_initiator.status();
ForwardCall(call_handler, std::move(*call_initiator));
if (!server_call_initiator.ok()) {
return server_call_initiator.status();
}
ForwardCall(child_call_handler,
std::move(*server_call_initiator));
return absl::OkStatus();
}));
}
@ -155,7 +176,6 @@ class InprocClientTransport final : public ClientTransport {
bool UsePromiseBasedTransport() {
if (!IsPromiseBasedInprocTransportEnabled()) return false;
CHECK(IsPromiseBasedClientCallEnabled());
CHECK(IsPromiseBasedServerCallEnabled());
return true;
}
@ -180,7 +200,7 @@ OrphanablePtr<Channel> MakeLameChannel(absl::string_view why,
OrphanablePtr<Channel> MakeInprocChannel(Server* server,
ChannelArgs client_channel_args) {
auto transports = MakeInProcessTransportPair();
auto transports = MakeInProcessTransportPair(server->channel_args());
auto client_transport = std::move(transports.first);
auto server_transport = std::move(transports.second);
auto error =
@ -205,8 +225,9 @@ OrphanablePtr<Channel> MakeInprocChannel(Server* server,
} // namespace
std::pair<OrphanablePtr<Transport>, OrphanablePtr<Transport>>
MakeInProcessTransportPair() {
auto server_transport = MakeOrphanable<InprocServerTransport>();
MakeInProcessTransportPair(const ChannelArgs& server_channel_args) {
auto server_transport =
MakeOrphanable<InprocServerTransport>(server_channel_args);
auto client_transport = server_transport->MakeClientTransport();
return std::make_pair(std::move(client_transport),
std::move(server_transport));

@ -30,7 +30,7 @@ extern grpc_core::TraceFlag grpc_inproc_trace;
namespace grpc_core {
std::pair<OrphanablePtr<Transport>, OrphanablePtr<Transport>>
MakeInProcessTransportPair();
MakeInProcessTransportPair(const ChannelArgs& server_channel_args);
}

@ -305,13 +305,6 @@ grpc_core::NextPromiseFactory ClientNext(grpc_channel_element* elem) {
};
}
grpc_core::NextPromiseFactory ServerNext(grpc_channel_element* elem) {
return [elem](grpc_core::CallArgs args) {
return elem->filter->make_call_promise(elem, std::move(args),
ServerNext(elem - 1));
};
}
} // namespace
grpc_core::ArenaPromise<grpc_core::ServerMetadataHandle>
@ -319,12 +312,6 @@ grpc_channel_stack::MakeClientCallPromise(grpc_core::CallArgs call_args) {
return ClientNext(grpc_channel_stack_element(this, 0))(std::move(call_args));
}
grpc_core::ArenaPromise<grpc_core::ServerMetadataHandle>
grpc_channel_stack::MakeServerCallPromise(grpc_core::CallArgs call_args) {
return ServerNext(grpc_channel_stack_element(this, this->count - 1))(
std::move(call_args));
}
void grpc_channel_stack::InitClientCallSpine(
grpc_core::CallSpineInterface* call) {
for (size_t i = 0; i < count; i++) {
@ -338,19 +325,6 @@ void grpc_channel_stack::InitClientCallSpine(
}
}
void grpc_channel_stack::InitServerCallSpine(
grpc_core::CallSpineInterface* call) {
for (size_t i = 0; i < count; i++) {
auto* elem = grpc_channel_stack_element(this, count - 1 - i);
if (elem->filter->init_call == nullptr) {
grpc_core::Crash(
absl::StrCat("Filter '", elem->filter->name,
"' does not support the call-v3 interface"));
}
elem->filter->init_call(elem, call);
}
}
void grpc_call_log_op(const char* file, int line, gpr_log_severity severity,
grpc_call_element* elem,
grpc_transport_stream_op_batch* op) {

@ -241,7 +241,6 @@ struct grpc_channel_stack {
MakeServerCallPromise(grpc_core::CallArgs call_args);
void InitClientCallSpine(grpc_core::CallSpineInterface* call);
void InitServerCallSpine(grpc_core::CallSpineInterface* call);
};
// A call stack tracks a set of related filters for one call, and guarantees

@ -34,12 +34,14 @@ GlobalInstrumentsRegistry::GetInstrumentList() {
return *instruments;
}
GlobalInstrumentsRegistry::GlobalUInt64CounterHandle
GlobalInstrumentsRegistry::RegisterUInt64Counter(
GlobalInstrumentsRegistry::InstrumentID
GlobalInstrumentsRegistry::RegisterInstrument(
GlobalInstrumentsRegistry::ValueType value_type,
GlobalInstrumentsRegistry::InstrumentType instrument_type,
absl::string_view name, absl::string_view description,
absl::string_view unit, absl::Span<const absl::string_view> label_keys,
absl::Span<const absl::string_view> optional_label_keys,
bool enable_by_default) {
absl::string_view unit, bool enable_by_default,
absl::Span<const absl::string_view> label_keys,
absl::Span<const absl::string_view> optional_label_keys) {
auto& instruments = GetInstrumentList();
for (const auto& descriptor : instruments) {
if (descriptor.name == name) {
@ -47,11 +49,11 @@ GlobalInstrumentsRegistry::RegisterUInt64Counter(
absl::StrFormat("Metric name %s has already been registered.", name));
}
}
uint32_t index = instruments.size();
InstrumentID index = instruments.size();
CHECK_LT(index, std::numeric_limits<uint32_t>::max());
GlobalInstrumentDescriptor descriptor;
descriptor.value_type = ValueType::kUInt64;
descriptor.instrument_type = InstrumentType::kCounter;
descriptor.value_type = value_type;
descriptor.instrument_type = instrument_type;
descriptor.index = index;
descriptor.enable_by_default = enable_by_default;
descriptor.name = name;
@ -61,169 +63,7 @@ GlobalInstrumentsRegistry::RegisterUInt64Counter(
descriptor.optional_label_keys = {optional_label_keys.begin(),
optional_label_keys.end()};
instruments.push_back(std::move(descriptor));
GlobalUInt64CounterHandle handle;
handle.index = index;
return handle;
}
GlobalInstrumentsRegistry::GlobalDoubleCounterHandle
GlobalInstrumentsRegistry::RegisterDoubleCounter(
absl::string_view name, absl::string_view description,
absl::string_view unit, absl::Span<const absl::string_view> label_keys,
absl::Span<const absl::string_view> optional_label_keys,
bool enable_by_default) {
auto& instruments = GetInstrumentList();
for (const auto& descriptor : instruments) {
if (descriptor.name == name) {
Crash(
absl::StrFormat("Metric name %s has already been registered.", name));
}
}
uint32_t index = instruments.size();
CHECK_LT(index, std::numeric_limits<uint32_t>::max());
GlobalInstrumentDescriptor descriptor;
descriptor.value_type = ValueType::kDouble;
descriptor.instrument_type = InstrumentType::kCounter;
descriptor.index = index;
descriptor.enable_by_default = enable_by_default;
descriptor.name = name;
descriptor.description = description;
descriptor.unit = unit;
descriptor.label_keys = {label_keys.begin(), label_keys.end()};
descriptor.optional_label_keys = {optional_label_keys.begin(),
optional_label_keys.end()};
instruments.push_back(std::move(descriptor));
GlobalDoubleCounterHandle handle;
handle.index = index;
return handle;
}
GlobalInstrumentsRegistry::GlobalUInt64HistogramHandle
GlobalInstrumentsRegistry::RegisterUInt64Histogram(
absl::string_view name, absl::string_view description,
absl::string_view unit, absl::Span<const absl::string_view> label_keys,
absl::Span<const absl::string_view> optional_label_keys,
bool enable_by_default) {
auto& instruments = GetInstrumentList();
for (const auto& descriptor : instruments) {
if (descriptor.name == name) {
Crash(
absl::StrFormat("Metric name %s has already been registered.", name));
}
}
uint32_t index = instruments.size();
CHECK_LT(index, std::numeric_limits<uint32_t>::max());
GlobalInstrumentDescriptor descriptor;
descriptor.value_type = ValueType::kUInt64;
descriptor.instrument_type = InstrumentType::kHistogram;
descriptor.index = index;
descriptor.enable_by_default = enable_by_default;
descriptor.name = name;
descriptor.description = description;
descriptor.unit = unit;
descriptor.label_keys = {label_keys.begin(), label_keys.end()};
descriptor.optional_label_keys = {optional_label_keys.begin(),
optional_label_keys.end()};
instruments.push_back(std::move(descriptor));
GlobalUInt64HistogramHandle handle;
handle.index = index;
return handle;
}
GlobalInstrumentsRegistry::GlobalDoubleHistogramHandle
GlobalInstrumentsRegistry::RegisterDoubleHistogram(
absl::string_view name, absl::string_view description,
absl::string_view unit, absl::Span<const absl::string_view> label_keys,
absl::Span<const absl::string_view> optional_label_keys,
bool enable_by_default) {
auto& instruments = GetInstrumentList();
for (const auto& descriptor : instruments) {
if (descriptor.name == name) {
Crash(
absl::StrFormat("Metric name %s has already been registered.", name));
}
}
uint32_t index = instruments.size();
CHECK_LT(index, std::numeric_limits<uint32_t>::max());
GlobalInstrumentDescriptor descriptor;
descriptor.value_type = ValueType::kDouble;
descriptor.instrument_type = InstrumentType::kHistogram;
descriptor.index = index;
descriptor.enable_by_default = enable_by_default;
descriptor.name = name;
descriptor.description = description;
descriptor.unit = unit;
descriptor.label_keys = {label_keys.begin(), label_keys.end()};
descriptor.optional_label_keys = {optional_label_keys.begin(),
optional_label_keys.end()};
instruments.push_back(std::move(descriptor));
GlobalDoubleHistogramHandle handle;
handle.index = index;
return handle;
}
GlobalInstrumentsRegistry::GlobalCallbackInt64GaugeHandle
GlobalInstrumentsRegistry::RegisterCallbackInt64Gauge(
absl::string_view name, absl::string_view description,
absl::string_view unit, absl::Span<const absl::string_view> label_keys,
absl::Span<const absl::string_view> optional_label_keys,
bool enable_by_default) {
auto& instruments = GetInstrumentList();
for (const auto& descriptor : instruments) {
if (descriptor.name == name) {
Crash(
absl::StrFormat("Metric name %s has already been registered.", name));
}
}
uint32_t index = instruments.size();
CHECK_LT(index, std::numeric_limits<uint32_t>::max());
GlobalInstrumentDescriptor descriptor;
descriptor.value_type = ValueType::kInt64;
descriptor.instrument_type = InstrumentType::kCallbackGauge;
descriptor.index = index;
descriptor.enable_by_default = enable_by_default;
descriptor.name = name;
descriptor.description = description;
descriptor.unit = unit;
descriptor.label_keys = {label_keys.begin(), label_keys.end()};
descriptor.optional_label_keys = {optional_label_keys.begin(),
optional_label_keys.end()};
instruments.push_back(std::move(descriptor));
GlobalCallbackInt64GaugeHandle handle;
handle.index = index;
return handle;
}
GlobalInstrumentsRegistry::GlobalCallbackDoubleGaugeHandle
GlobalInstrumentsRegistry::RegisterCallbackDoubleGauge(
absl::string_view name, absl::string_view description,
absl::string_view unit, absl::Span<const absl::string_view> label_keys,
absl::Span<const absl::string_view> optional_label_keys,
bool enable_by_default) {
auto& instruments = GetInstrumentList();
for (const auto& descriptor : instruments) {
if (descriptor.name == name) {
Crash(
absl::StrFormat("Metric name %s has already been registered.", name));
}
}
uint32_t index = instruments.size();
CHECK_LT(index, std::numeric_limits<uint32_t>::max());
GlobalInstrumentDescriptor descriptor;
descriptor.value_type = ValueType::kDouble;
descriptor.instrument_type = InstrumentType::kCallbackGauge;
descriptor.index = index;
descriptor.enable_by_default = enable_by_default;
descriptor.name = name;
descriptor.description = description;
descriptor.unit = unit;
descriptor.label_keys = {label_keys.begin(), label_keys.end()};
descriptor.optional_label_keys = {optional_label_keys.begin(),
optional_label_keys.end()};
instruments.push_back(std::move(descriptor));
GlobalCallbackDoubleGaugeHandle handle;
handle.index = index;
return handle;
return index;
}
void GlobalInstrumentsRegistry::ForEach(
@ -242,7 +82,7 @@ GlobalInstrumentsRegistry::GetInstrumentDescriptor(
RegisteredMetricCallback::RegisteredMetricCallback(
GlobalStatsPluginRegistry::StatsPluginGroup& stats_plugin_group,
absl::AnyInvocable<void(CallbackMetricReporter&)> callback,
std::vector<GlobalInstrumentsRegistry::GlobalCallbackHandle> metrics,
std::vector<GlobalInstrumentsRegistry::GlobalInstrumentHandle> metrics,
Duration min_interval)
: stats_plugin_group_(stats_plugin_group),
callback_(std::move(callback)),
@ -259,15 +99,6 @@ RegisteredMetricCallback::~RegisteredMetricCallback() {
}
}
std::unique_ptr<RegisteredMetricCallback>
GlobalStatsPluginRegistry::StatsPluginGroup::RegisterCallback(
absl::AnyInvocable<void(CallbackMetricReporter&)> callback,
std::vector<GlobalInstrumentsRegistry::GlobalCallbackHandle> metrics,
Duration min_interval) {
return std::make_unique<RegisteredMetricCallback>(
*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) {

@ -17,6 +17,7 @@
#include <cstdint>
#include <memory>
#include <type_traits>
#include <vector>
#include "absl/functional/any_invocable.h"
@ -45,6 +46,27 @@ constexpr absl::string_view kMetricLabelTarget = "grpc.target";
// startup, before the execution of the main function (during dynamic
// initialization time). Using this API after the main function begins may
// result into missing instruments. This API is thread-unsafe.
//
// The registration of instruments is done through the templated
// RegistrationBuilder API and gets back a handle with an opaque type. At
// runtime, the handle should be used with the StatsPluginGroup API to record
// metrics for the instruments.
//
// At dynamic initialization time:
// const auto kMetricHandle =
// GlobalInstrumentsRegistry::RegisterUInt64Counter(
// "name",
// "description",
// "unit", /*enable_by_default=*/false)
// .Labels(kLabel1, kLabel2, kLabel3)
// .OptionalLabels(kOptionalLabel1, kOptionalLabel2)
// .Build();
//
// At runtime time:
// stats_plugin_group.AddCounter(kMetricHandle, 1,
// {"label_value_1", "label_value_2", "label_value_3"},
// {"optional_label_value_1", "optional_label_value_2"});
//
class GlobalInstrumentsRegistry {
public:
enum class ValueType {
@ -78,46 +100,113 @@ class GlobalInstrumentsRegistry {
// runs or between different versions.
InstrumentID index;
};
struct GlobalUInt64CounterHandle : public GlobalInstrumentHandle {};
struct GlobalDoubleCounterHandle : public GlobalInstrumentHandle {};
struct GlobalUInt64HistogramHandle : public GlobalInstrumentHandle {};
struct GlobalDoubleHistogramHandle : public GlobalInstrumentHandle {};
struct GlobalCallbackInt64GaugeHandle : public GlobalInstrumentHandle {};
struct GlobalCallbackDoubleGaugeHandle : public GlobalInstrumentHandle {};
using GlobalCallbackHandle = absl::variant<GlobalCallbackInt64GaugeHandle,
GlobalCallbackDoubleGaugeHandle>;
template <ValueType V, InstrumentType I, size_t M, size_t N>
struct TypedGlobalInstrumentHandle : public GlobalInstrumentHandle {};
template <ValueType V, InstrumentType I, std::size_t M, std::size_t N>
class RegistrationBuilder {
public:
template <typename... Args>
RegistrationBuilder<V, I, sizeof...(Args), N> Labels(Args&&... args) {
return RegistrationBuilder<V, I, sizeof...(Args), N>(
name_, description_, unit_, enable_by_default_,
std::array<absl::string_view, sizeof...(Args)>({args...}),
optional_label_keys_);
}
template <typename... Args>
RegistrationBuilder<V, I, M, sizeof...(Args)> OptionalLabels(
Args&&... args) {
return RegistrationBuilder<V, I, M, sizeof...(Args)>(
name_, description_, unit_, enable_by_default_, label_keys_,
std::array<absl::string_view, sizeof...(Args)>({args...}));
}
TypedGlobalInstrumentHandle<V, I, M, N> Build() {
TypedGlobalInstrumentHandle<V, I, M, N> handle;
handle.index = RegisterInstrument(V, I, name_, description_, unit_,
enable_by_default_, label_keys_,
optional_label_keys_);
return handle;
}
private:
friend class GlobalInstrumentsRegistry;
RegistrationBuilder(absl::string_view name, absl::string_view description,
absl::string_view unit, bool enable_by_default)
: name_(name),
description_(description),
unit_(unit),
enable_by_default_(enable_by_default) {}
RegistrationBuilder(absl::string_view name, absl::string_view description,
absl::string_view unit, bool enable_by_default,
std::array<absl::string_view, M> label_keys,
std::array<absl::string_view, N> optional_label_keys)
: name_(name),
description_(description),
unit_(unit),
enable_by_default_(enable_by_default),
label_keys_(std::move(label_keys)),
optional_label_keys_(std::move(optional_label_keys)) {}
absl::string_view name_;
absl::string_view description_;
absl::string_view unit_;
bool enable_by_default_;
std::array<absl::string_view, M> label_keys_;
std::array<absl::string_view, N> optional_label_keys_;
};
// Creates instrument in the GlobalInstrumentsRegistry.
static GlobalUInt64CounterHandle RegisterUInt64Counter(
absl::string_view name, absl::string_view description,
absl::string_view unit, absl::Span<const absl::string_view> label_keys,
absl::Span<const absl::string_view> optional_label_keys,
bool enable_by_default);
static GlobalDoubleCounterHandle RegisterDoubleCounter(
absl::string_view name, absl::string_view description,
absl::string_view unit, absl::Span<const absl::string_view> label_keys,
absl::Span<const absl::string_view> optional_label_keys,
bool enable_by_default);
static GlobalUInt64HistogramHandle RegisterUInt64Histogram(
absl::string_view name, absl::string_view description,
absl::string_view unit, absl::Span<const absl::string_view> label_keys,
absl::Span<const absl::string_view> optional_label_keys,
bool enable_by_default);
static GlobalDoubleHistogramHandle RegisterDoubleHistogram(
absl::string_view name, absl::string_view description,
absl::string_view unit, absl::Span<const absl::string_view> label_keys,
absl::Span<const absl::string_view> optional_label_keys,
bool enable_by_default);
static GlobalCallbackInt64GaugeHandle RegisterCallbackInt64Gauge(
absl::string_view name, absl::string_view description,
absl::string_view unit, absl::Span<const absl::string_view> label_keys,
absl::Span<const absl::string_view> optional_label_keys,
bool enable_by_default);
static GlobalCallbackDoubleGaugeHandle RegisterCallbackDoubleGauge(
absl::string_view name, absl::string_view description,
absl::string_view unit, absl::Span<const absl::string_view> label_keys,
absl::Span<const absl::string_view> optional_label_keys,
bool enable_by_default);
static RegistrationBuilder<ValueType::kUInt64, InstrumentType::kCounter, 0, 0>
RegisterUInt64Counter(absl::string_view name, absl::string_view description,
absl::string_view unit, bool enable_by_default) {
return RegistrationBuilder<ValueType::kUInt64, InstrumentType::kCounter, 0,
0>(name, description, unit, enable_by_default);
}
static RegistrationBuilder<ValueType::kDouble, InstrumentType::kCounter, 0, 0>
RegisterDoubleCounter(absl::string_view name, absl::string_view description,
absl::string_view unit, bool enable_by_default) {
return RegistrationBuilder<ValueType::kDouble, InstrumentType::kCounter, 0,
0>(name, description, unit, enable_by_default);
}
static RegistrationBuilder<ValueType::kUInt64, InstrumentType::kHistogram, 0,
0>
RegisterUInt64Histogram(absl::string_view name, absl::string_view description,
absl::string_view unit, bool enable_by_default) {
return RegistrationBuilder<ValueType::kUInt64, InstrumentType::kHistogram,
0, 0>(name, description, unit,
enable_by_default);
}
static RegistrationBuilder<ValueType::kDouble, InstrumentType::kHistogram, 0,
0>
RegisterDoubleHistogram(absl::string_view name, absl::string_view description,
absl::string_view unit, bool enable_by_default) {
return RegistrationBuilder<ValueType::kDouble, InstrumentType::kHistogram,
0, 0>(name, description, unit,
enable_by_default);
}
static RegistrationBuilder<ValueType::kInt64, InstrumentType::kCallbackGauge,
0, 0>
RegisterCallbackInt64Gauge(absl::string_view name,
absl::string_view description,
absl::string_view unit, bool enable_by_default) {
return RegistrationBuilder<ValueType::kInt64,
InstrumentType::kCallbackGauge, 0, 0>(
name, description, unit, enable_by_default);
}
static RegistrationBuilder<ValueType::kDouble, InstrumentType::kCallbackGauge,
0, 0>
RegisterCallbackDoubleGauge(absl::string_view name,
absl::string_view description,
absl::string_view unit, bool enable_by_default) {
return RegistrationBuilder<ValueType::kDouble,
InstrumentType::kCallbackGauge, 0, 0>(
name, description, unit, enable_by_default);
}
static void ForEach(
absl::FunctionRef<void(const GlobalInstrumentDescriptor&)> f);
@ -131,6 +220,12 @@ class GlobalInstrumentsRegistry {
static std::vector<GlobalInstrumentsRegistry::GlobalInstrumentDescriptor>&
GetInstrumentList();
static InstrumentID RegisterInstrument(
ValueType value_type, InstrumentType instrument_type,
absl::string_view name, absl::string_view description,
absl::string_view unit, bool enable_by_default,
absl::Span<const absl::string_view> label_keys,
absl::Span<const absl::string_view> optional_label_keys);
};
// An interface for implementing callback-style metrics.
@ -139,13 +234,35 @@ class CallbackMetricReporter {
public:
virtual ~CallbackMetricReporter() = default;
virtual void Report(
GlobalInstrumentsRegistry::GlobalCallbackInt64GaugeHandle handle,
int64_t value, absl::Span<const absl::string_view> label_values,
template <std::size_t M, std::size_t N>
void Report(
GlobalInstrumentsRegistry::TypedGlobalInstrumentHandle<
GlobalInstrumentsRegistry::ValueType::kInt64,
GlobalInstrumentsRegistry::InstrumentType::kCallbackGauge, M, N>
handle,
int64_t value, std::array<absl::string_view, M> label_values,
std::array<absl::string_view, N> optional_values) {
ReportInt64(handle, value, label_values, optional_values);
}
template <std::size_t M, std::size_t N>
void Report(
GlobalInstrumentsRegistry::TypedGlobalInstrumentHandle<
GlobalInstrumentsRegistry::ValueType::kDouble,
GlobalInstrumentsRegistry::InstrumentType::kCallbackGauge, M, N>
handle,
double value, std::array<absl::string_view, M> label_values,
std::array<absl::string_view, N> optional_values) {
ReportDouble(handle, value, label_values, optional_values);
}
private:
virtual void ReportInt64(
GlobalInstrumentsRegistry::GlobalInstrumentHandle handle, int64_t value,
absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) = 0;
virtual void Report(
GlobalInstrumentsRegistry::GlobalCallbackDoubleGaugeHandle handle,
double value, absl::Span<const absl::string_view> label_values,
virtual void ReportDouble(
GlobalInstrumentsRegistry::GlobalInstrumentHandle handle, double value,
absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) = 0;
};
@ -179,15 +296,15 @@ class StatsPlugin {
// 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,
GlobalInstrumentsRegistry::GlobalInstrumentHandle handle, uint64_t value,
absl::Span<const absl::string_view> label_values,
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,
GlobalInstrumentsRegistry::GlobalInstrumentHandle handle, double value,
absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_label_values) = 0;
// Records a uint64 \a value to the histogram specified by \a handle. \a
@ -195,16 +312,16 @@ class StatsPlugin {
// 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,
GlobalInstrumentsRegistry::GlobalInstrumentHandle handle, uint64_t value,
absl::Span<const absl::string_view> label_values,
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,
GlobalInstrumentsRegistry::GlobalInstrumentHandle handle, double value,
absl::Span<const absl::string_view> label_values,
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).
@ -255,20 +372,53 @@ class GlobalStatsPluginRegistry {
}
// 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) {
template <std::size_t M, std::size_t N>
void AddCounter(
GlobalInstrumentsRegistry::TypedGlobalInstrumentHandle<
GlobalInstrumentsRegistry::ValueType::kUInt64,
GlobalInstrumentsRegistry::InstrumentType::kCounter, M, N>
handle,
uint64_t value, std::array<absl::string_view, M> label_values,
std::array<absl::string_view, N> optional_values) {
for (auto& state : plugins_state_) {
state.plugin->AddCounter(handle, value, label_values, optional_values);
}
}
template <std::size_t M, std::size_t N>
void AddCounter(
GlobalInstrumentsRegistry::TypedGlobalInstrumentHandle<
GlobalInstrumentsRegistry::ValueType::kDouble,
GlobalInstrumentsRegistry::InstrumentType::kCounter, M, N>
handle,
double value, std::array<absl::string_view, M> label_values,
std::array<absl::string_view, N> optional_values) {
for (auto& state : plugins_state_) {
state.plugin->AddCounter(handle, value, label_values, optional_values);
}
}
// Records a value to a histogram in all stats plugins within the group. See
// the StatsPlugin interface for more documentation and valid types.
template <class HandleType, class ValueType>
void RecordHistogram(HandleType handle, ValueType value,
absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) {
template <std::size_t M, std::size_t N>
void RecordHistogram(
GlobalInstrumentsRegistry::TypedGlobalInstrumentHandle<
GlobalInstrumentsRegistry::ValueType::kUInt64,
GlobalInstrumentsRegistry::InstrumentType::kHistogram, M, N>
handle,
uint64_t value, std::array<absl::string_view, M> label_values,
std::array<absl::string_view, N> optional_values) {
for (auto& state : plugins_state_) {
state.plugin->RecordHistogram(handle, value, label_values,
optional_values);
}
}
template <std::size_t M, std::size_t N>
void RecordHistogram(
GlobalInstrumentsRegistry::TypedGlobalInstrumentHandle<
GlobalInstrumentsRegistry::ValueType::kDouble,
GlobalInstrumentsRegistry::InstrumentType::kHistogram, M, N>
handle,
double value, std::array<absl::string_view, M> label_values,
std::array<absl::string_view, N> optional_values) {
for (auto& state : plugins_state_) {
state.plugin->RecordHistogram(handle, value, label_values,
optional_values);
@ -285,11 +435,17 @@ class GlobalStatsPluginRegistry {
// the lifetime of the callback; when the returned object is
// destroyed, the callback is de-registered. The returned object
// must not outlive the StatsPluginGroup object that created it.
template <typename... Args>
GRPC_MUST_USE_RESULT std::unique_ptr<RegisteredMetricCallback>
RegisterCallback(
absl::AnyInvocable<void(CallbackMetricReporter&)> callback,
std::vector<GlobalInstrumentsRegistry::GlobalCallbackHandle> metrics,
Duration min_interval = Duration::Seconds(5));
RegisterCallback(absl::AnyInvocable<void(CallbackMetricReporter&)> callback,
Duration min_interval, Args... args) {
AssertIsCallbackGaugeHandle(args...);
return std::make_unique<RegisteredMetricCallback>(
*this, std::move(callback),
std::vector<GlobalInstrumentsRegistry::GlobalInstrumentHandle>{
args...},
min_interval);
}
// Adds all available client call tracers associated with the stats plugins
// within the group to \a call_context.
@ -307,6 +463,24 @@ class GlobalStatsPluginRegistry {
std::shared_ptr<StatsPlugin> plugin;
};
// C++17 has fold expression that may simplify this.
template <GlobalInstrumentsRegistry::ValueType V,
GlobalInstrumentsRegistry::InstrumentType I, size_t M, size_t N>
static constexpr void AssertIsCallbackGaugeHandle(
GlobalInstrumentsRegistry::TypedGlobalInstrumentHandle<V, I, M, N>) {
static_assert(V == GlobalInstrumentsRegistry::ValueType::kInt64 ||
V == GlobalInstrumentsRegistry::ValueType::kDouble,
"ValueType must be kInt64 or kDouble");
static_assert(
I == GlobalInstrumentsRegistry::InstrumentType::kCallbackGauge,
"InstrumentType must be kCallbackGauge");
}
template <typename T, typename... Args>
static constexpr void AssertIsCallbackGaugeHandle(T t, Args&&... args) {
AssertIsCallbackGaugeHandle(t);
AssertIsCallbackGaugeHandle(args...);
}
std::vector<PluginState> plugins_state_;
};
@ -335,7 +509,7 @@ class RegisteredMetricCallback {
RegisteredMetricCallback(
GlobalStatsPluginRegistry::StatsPluginGroup& stats_plugin_group,
absl::AnyInvocable<void(CallbackMetricReporter&)> callback,
std::vector<GlobalInstrumentsRegistry::GlobalCallbackHandle> metrics,
std::vector<GlobalInstrumentsRegistry::GlobalInstrumentHandle> metrics,
Duration min_interval);
~RegisteredMetricCallback();
@ -344,8 +518,8 @@ class RegisteredMetricCallback {
void Run(CallbackMetricReporter& reporter) { callback_(reporter); }
// Returns the set of metrics that this callback will modify.
const std::vector<GlobalInstrumentsRegistry::GlobalCallbackHandle>& metrics()
const {
const std::vector<GlobalInstrumentsRegistry::GlobalInstrumentHandle>&
metrics() const {
return metrics_;
}
@ -356,7 +530,7 @@ class RegisteredMetricCallback {
private:
GlobalStatsPluginRegistry::StatsPluginGroup& stats_plugin_group_;
absl::AnyInvocable<void(CallbackMetricReporter&)> callback_;
std::vector<GlobalInstrumentsRegistry::GlobalCallbackHandle> metrics_;
std::vector<GlobalInstrumentsRegistry::GlobalInstrumentHandle> metrics_;
Duration min_interval_;
};

@ -112,6 +112,13 @@ class EventEngineSupportsFdExtension {
int fd, const EndpointConfig& config,
MemoryAllocator memory_allocator) = 0;
/// Creates an EventEngine::Endpoint from an fd which is already assumed to be
/// connected to a remote peer. See \a CreatePosixEndpointFromFd for details.
/// This has the same behavior, but the \a memory_allocator is taken from the
/// EndpointConfig's resource quota.
virtual std::unique_ptr<EventEngine::Endpoint> CreateEndpointFromFd(
int fd, const EndpointConfig& config) = 0;
/// Called when the posix listener has accepted a new client connection.
/// \a listener_fd - The listening socket fd that accepted the new client
/// connection.

@ -677,6 +677,22 @@ PosixEventEngine::CreatePosixEndpointFromFd(int fd,
#endif // GRPC_PLATFORM_SUPPORTS_POSIX_POLLING
}
std::unique_ptr<EventEngine::Endpoint> PosixEventEngine::CreateEndpointFromFd(
int fd, const EndpointConfig& config) {
auto options = TcpOptionsFromEndpointConfig(config);
MemoryAllocator allocator;
if (options.memory_allocator_factory != nullptr) {
return CreatePosixEndpointFromFd(
fd, config,
options.memory_allocator_factory->CreateMemoryAllocator(
absl::StrCat("allocator:", fd)));
}
return CreatePosixEndpointFromFd(
fd, config,
options.resource_quota->memory_quota()->CreateMemoryAllocator(
absl::StrCat("allocator:", fd)));
}
absl::StatusOr<std::unique_ptr<EventEngine::Listener>>
PosixEventEngine::CreateListener(
Listener::AcceptCallback on_accept,

@ -172,6 +172,8 @@ class PosixEventEngine final : public PosixEventEngineWithFdSupport,
std::unique_ptr<EventEngine::Endpoint> CreatePosixEndpointFromFd(
int fd, const EndpointConfig& config,
MemoryAllocator memory_allocator) override;
std::unique_ptr<EventEngine::Endpoint> CreateEndpointFromFd(
int fd, const EndpointConfig& config) override;
absl::StatusOr<std::unique_ptr<Listener>> CreateListener(
Listener::AcceptCallback on_accept,

@ -227,18 +227,19 @@ void WorkStealingThreadPool::PostforkChild() { pool_->Postfork(); }
WorkStealingThreadPool::WorkStealingThreadPoolImpl::WorkStealingThreadPoolImpl(
size_t reserve_threads)
: reserve_threads_(reserve_threads), queue_(this), lifeguard_(this) {}
: reserve_threads_(reserve_threads), queue_(this) {}
void WorkStealingThreadPool::WorkStealingThreadPoolImpl::Start() {
for (size_t i = 0; i < reserve_threads_; i++) {
StartThread();
}
lifeguard_.Start();
grpc_core::MutexLock lock(&lifeguard_ptr_mu_);
lifeguard_ = std::make_unique<Lifeguard>(this);
}
void WorkStealingThreadPool::WorkStealingThreadPoolImpl::Run(
EventEngine::Closure* closure) {
DCHECK(quiesced_.load(std::memory_order_relaxed) == false);
CHECK(!IsQuiesced());
if (g_local_queue != nullptr && g_local_queue->owner() == this) {
g_local_queue->Add(closure);
} else {
@ -283,7 +284,8 @@ void WorkStealingThreadPool::WorkStealingThreadPoolImpl::Quiesce() {
}
CHECK(queue_.Empty());
quiesced_.store(true, std::memory_order_relaxed);
lifeguard_.BlockUntilShutdownAndReset();
grpc_core::MutexLock lock(&lifeguard_ptr_mu_);
lifeguard_.reset();
}
bool WorkStealingThreadPool::WorkStealingThreadPoolImpl::SetThrottled(
@ -325,7 +327,8 @@ void WorkStealingThreadPool::WorkStealingThreadPoolImpl::PrepareFork() {
if (!threads_were_shut_down.ok() && g_log_verbose_failures) {
DumpStacksAndCrash();
}
lifeguard_.BlockUntilShutdownAndReset();
grpc_core::MutexLock lock(&lifeguard_ptr_mu_);
lifeguard_.reset();
}
void WorkStealingThreadPool::WorkStealingThreadPoolImpl::Postfork() {
@ -374,9 +377,7 @@ WorkStealingThreadPool::WorkStealingThreadPoolImpl::Lifeguard::Lifeguard(
.set_max_backoff(kLifeguardMaxSleepBetweenChecks)
.set_multiplier(1.3)),
lifeguard_should_shut_down_(std::make_unique<grpc_core::Notification>()),
lifeguard_is_shut_down_(std::make_unique<grpc_core::Notification>()) {}
void WorkStealingThreadPool::WorkStealingThreadPoolImpl::Lifeguard::Start() {
lifeguard_is_shut_down_(std::make_unique<grpc_core::Notification>()) {
// lifeguard_running_ is set early to avoid a quiesce race while the
// lifeguard is still starting up.
lifeguard_running_.store(true);
@ -411,8 +412,7 @@ void WorkStealingThreadPool::WorkStealingThreadPoolImpl::Lifeguard::
lifeguard_is_shut_down_->Notify();
}
void WorkStealingThreadPool::WorkStealingThreadPoolImpl::Lifeguard::
BlockUntilShutdownAndReset() {
WorkStealingThreadPool::WorkStealingThreadPoolImpl::Lifeguard::~Lifeguard() {
lifeguard_should_shut_down_->Notify();
while (lifeguard_running_.load(std::memory_order_relaxed)) {
GRPC_LOG_EVERY_N_SEC_DELAYED(kBlockingQuiesceLogRateSeconds, GPR_DEBUG,

@ -155,11 +155,7 @@ class WorkStealingThreadPool final : public ThreadPool {
class Lifeguard {
public:
explicit Lifeguard(WorkStealingThreadPoolImpl* pool);
// Start the lifeguard thread.
void Start();
// Block until the lifeguard thread is shut down.
// Afterwards, reset the lifeguard state so it can start again cleanly.
void BlockUntilShutdownAndReset();
~Lifeguard();
private:
// The main body of the lifeguard thread.
@ -194,7 +190,8 @@ class WorkStealingThreadPool final : public ThreadPool {
// at a time.
std::atomic<bool> throttled_{false};
WorkSignal work_signal_;
Lifeguard lifeguard_;
grpc_core::Mutex lifeguard_ptr_mu_;
std::unique_ptr<Lifeguard> lifeguard_ ABSL_GUARDED_BY(lifeguard_ptr_mu_);
// Set of threads for verbose failure debugging
grpc_core::Mutex thd_set_mu_;
absl::flat_hash_set<gpr_thd_id> thds_ ABSL_GUARDED_BY(thd_set_mu_);

@ -88,23 +88,17 @@ const char* const additional_constraints_promise_based_client_call = "{}";
const uint8_t required_experiments_promise_based_client_call[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdEventEngineClient),
static_cast<uint8_t>(grpc_core::kExperimentIdEventEngineListener)};
const char* const description_promise_based_server_call =
"If set, use the new gRPC promise based call code when it's appropriate "
"(ie when all filters in a stack are promise based)";
const char* const additional_constraints_promise_based_server_call = "{}";
const char* const description_chaotic_good =
"If set, enable the chaotic good load transport (this is mostly here for "
"testing)";
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)};
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedClientCall)};
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::kExperimentIdPromiseBasedClientCall)};
const char* const description_rstpit =
"On RST_STREAM on a server, reduce MAX_CONCURRENT_STREAMS for a short "
"duration";
@ -184,15 +178,13 @@ const ExperimentMetadata g_experiment_metadata[] = {
{"promise_based_client_call", description_promise_based_client_call,
additional_constraints_promise_based_client_call,
required_experiments_promise_based_client_call, 2, false, true},
{"promise_based_server_call", description_promise_based_server_call,
additional_constraints_promise_based_server_call, nullptr, 0, false, true},
{"chaotic_good", description_chaotic_good,
additional_constraints_chaotic_good, required_experiments_chaotic_good, 2,
additional_constraints_chaotic_good, required_experiments_chaotic_good, 1,
false, true},
{"promise_based_inproc_transport",
description_promise_based_inproc_transport,
additional_constraints_promise_based_inproc_transport,
required_experiments_promise_based_inproc_transport, 2, false, false},
required_experiments_promise_based_inproc_transport, 1, false, false},
{"rstpit", description_rstpit, additional_constraints_rstpit, nullptr, 0,
false, true},
{"schedule_cancellation_over_write",
@ -288,23 +280,17 @@ const char* const additional_constraints_promise_based_client_call = "{}";
const uint8_t required_experiments_promise_based_client_call[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdEventEngineClient),
static_cast<uint8_t>(grpc_core::kExperimentIdEventEngineListener)};
const char* const description_promise_based_server_call =
"If set, use the new gRPC promise based call code when it's appropriate "
"(ie when all filters in a stack are promise based)";
const char* const additional_constraints_promise_based_server_call = "{}";
const char* const description_chaotic_good =
"If set, enable the chaotic good load transport (this is mostly here for "
"testing)";
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)};
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedClientCall)};
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::kExperimentIdPromiseBasedClientCall)};
const char* const description_rstpit =
"On RST_STREAM on a server, reduce MAX_CONCURRENT_STREAMS for a short "
"duration";
@ -358,7 +344,7 @@ const ExperimentMetadata g_experiment_metadata[] = {
{"client_privacy", description_client_privacy,
additional_constraints_client_privacy, nullptr, 0, false, false},
{"event_engine_client", description_event_engine_client,
additional_constraints_event_engine_client, nullptr, 0, false, true},
additional_constraints_event_engine_client, nullptr, 0, true, true},
{"event_engine_dns", description_event_engine_dns,
additional_constraints_event_engine_dns, nullptr, 0, false, false},
{"event_engine_listener", description_event_engine_listener,
@ -384,15 +370,13 @@ const ExperimentMetadata g_experiment_metadata[] = {
{"promise_based_client_call", description_promise_based_client_call,
additional_constraints_promise_based_client_call,
required_experiments_promise_based_client_call, 2, false, true},
{"promise_based_server_call", description_promise_based_server_call,
additional_constraints_promise_based_server_call, nullptr, 0, false, true},
{"chaotic_good", description_chaotic_good,
additional_constraints_chaotic_good, required_experiments_chaotic_good, 2,
additional_constraints_chaotic_good, required_experiments_chaotic_good, 1,
false, true},
{"promise_based_inproc_transport",
description_promise_based_inproc_transport,
additional_constraints_promise_based_inproc_transport,
required_experiments_promise_based_inproc_transport, 2, false, false},
required_experiments_promise_based_inproc_transport, 1, false, false},
{"rstpit", description_rstpit, additional_constraints_rstpit, nullptr, 0,
false, true},
{"schedule_cancellation_over_write",
@ -488,23 +472,17 @@ const char* const additional_constraints_promise_based_client_call = "{}";
const uint8_t required_experiments_promise_based_client_call[] = {
static_cast<uint8_t>(grpc_core::kExperimentIdEventEngineClient),
static_cast<uint8_t>(grpc_core::kExperimentIdEventEngineListener)};
const char* const description_promise_based_server_call =
"If set, use the new gRPC promise based call code when it's appropriate "
"(ie when all filters in a stack are promise based)";
const char* const additional_constraints_promise_based_server_call = "{}";
const char* const description_chaotic_good =
"If set, enable the chaotic good load transport (this is mostly here for "
"testing)";
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)};
static_cast<uint8_t>(grpc_core::kExperimentIdPromiseBasedClientCall)};
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::kExperimentIdPromiseBasedClientCall)};
const char* const description_rstpit =
"On RST_STREAM on a server, reduce MAX_CONCURRENT_STREAMS for a short "
"duration";
@ -584,15 +562,13 @@ const ExperimentMetadata g_experiment_metadata[] = {
{"promise_based_client_call", description_promise_based_client_call,
additional_constraints_promise_based_client_call,
required_experiments_promise_based_client_call, 2, false, true},
{"promise_based_server_call", description_promise_based_server_call,
additional_constraints_promise_based_server_call, nullptr, 0, false, true},
{"chaotic_good", description_chaotic_good,
additional_constraints_chaotic_good, required_experiments_chaotic_good, 2,
additional_constraints_chaotic_good, required_experiments_chaotic_good, 1,
false, true},
{"promise_based_inproc_transport",
description_promise_based_inproc_transport,
additional_constraints_promise_based_inproc_transport,
required_experiments_promise_based_inproc_transport, 2, false, false},
required_experiments_promise_based_inproc_transport, 1, false, false},
{"rstpit", description_rstpit, additional_constraints_rstpit, nullptr, 0,
false, true},
{"schedule_cancellation_over_write",

@ -79,7 +79,6 @@ inline bool IsPendingQueueCapEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_PICK_FIRST_NEW
inline bool IsPickFirstNewEnabled() { return true; }
inline bool IsPromiseBasedClientCallEnabled() { return false; }
inline bool IsPromiseBasedServerCallEnabled() { return false; }
inline bool IsChaoticGoodEnabled() { return false; }
inline bool IsPromiseBasedInprocTransportEnabled() { return false; }
inline bool IsRstpitEnabled() { return false; }
@ -100,7 +99,8 @@ inline bool IsCallStatusOverrideOnCancellationEnabled() { return true; }
inline bool IsCallV3Enabled() { return false; }
inline bool IsCanaryClientPrivacyEnabled() { return false; }
inline bool IsClientPrivacyEnabled() { return false; }
inline bool IsEventEngineClientEnabled() { return false; }
#define GRPC_EXPERIMENT_IS_INCLUDED_EVENT_ENGINE_CLIENT
inline bool IsEventEngineClientEnabled() { return true; }
inline bool IsEventEngineDnsEnabled() { return false; }
#define GRPC_EXPERIMENT_IS_INCLUDED_EVENT_ENGINE_LISTENER
inline bool IsEventEngineListenerEnabled() { return true; }
@ -118,7 +118,6 @@ inline bool IsPendingQueueCapEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_PICK_FIRST_NEW
inline bool IsPickFirstNewEnabled() { return true; }
inline bool IsPromiseBasedClientCallEnabled() { return false; }
inline bool IsPromiseBasedServerCallEnabled() { return false; }
inline bool IsChaoticGoodEnabled() { return false; }
inline bool IsPromiseBasedInprocTransportEnabled() { return false; }
inline bool IsRstpitEnabled() { return false; }
@ -158,7 +157,6 @@ inline bool IsPendingQueueCapEnabled() { return true; }
#define GRPC_EXPERIMENT_IS_INCLUDED_PICK_FIRST_NEW
inline bool IsPickFirstNewEnabled() { return true; }
inline bool IsPromiseBasedClientCallEnabled() { return false; }
inline bool IsPromiseBasedServerCallEnabled() { return false; }
inline bool IsChaoticGoodEnabled() { return false; }
inline bool IsPromiseBasedInprocTransportEnabled() { return false; }
inline bool IsRstpitEnabled() { return false; }
@ -194,7 +192,6 @@ enum ExperimentIds {
kExperimentIdPendingQueueCap,
kExperimentIdPickFirstNew,
kExperimentIdPromiseBasedClientCall,
kExperimentIdPromiseBasedServerCall,
kExperimentIdChaoticGood,
kExperimentIdPromiseBasedInprocTransport,
kExperimentIdRstpit,
@ -276,10 +273,6 @@ inline bool IsPickFirstNewEnabled() {
inline bool IsPromiseBasedClientCallEnabled() {
return IsExperimentEnabled(kExperimentIdPromiseBasedClientCall);
}
#define GRPC_EXPERIMENT_IS_INCLUDED_PROMISE_BASED_SERVER_CALL
inline bool IsPromiseBasedServerCallEnabled() {
return IsExperimentEnabled(kExperimentIdPromiseBasedServerCall);
}
#define GRPC_EXPERIMENT_IS_INCLUDED_CHAOTIC_GOOD
inline bool IsChaoticGoodEnabled() {
return IsExperimentEnabled(kExperimentIdChaoticGood);

@ -64,7 +64,7 @@
If set, enable the chaotic good load transport (this is mostly here for testing)
expiry: 2024/09/09
owner: ctiller@google.com
requires: [promise_based_client_call, promise_based_server_call]
requires: [promise_based_client_call]
test_tags: [core_end2end_test]
- name: client_privacy
description:
@ -170,14 +170,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]
- name: promise_based_server_call
description:
If set, use the new gRPC promise based call code when it's appropriate
(ie when all filters in a stack are promise based)
expiry: 2024/06/14
owner: ctiller@google.com
test_tags: ["core_end2end_test", "logging_test"]
requires: [promise_based_client_call]
- name: rstpit
description:
On RST_STREAM on a server, reduce MAX_CONCURRENT_STREAMS for a short duration

@ -58,9 +58,7 @@
# not tested on iOS at all
ios: broken
posix: false
# TODO(hork): resolve when the client end2end test flake rate reduces to
# a tolerable amount.
windows: false
windows: true
- name: event_engine_dns
default:
# not tested on iOS at all
@ -96,8 +94,6 @@
ios: broken
windows: broken
posix: false
- name: promise_based_server_call
default: false
- name: rstpit
default: false
- name: schedule_cancellation_over_write

@ -57,23 +57,4 @@ void gpr_log(const char* file, int line, gpr_log_severity severity,
free(message);
}
void gpr_platform_log(gpr_log_func_args* args) {
const char* final_slash;
const char* display_file;
char* output = NULL;
final_slash = strrchr(args->file, '/');
if (final_slash == NULL)
display_file = args->file;
else
display_file = final_slash + 1;
asprintf(&output, "%s:%d] %s", display_file, args->line, args->message);
__android_log_write(severity_to_log_priority(args->severity), "GRPC", output);
// allocated by asprintf => use free, not gpr_free
free(output);
}
#endif // GPR_ANDROID

@ -47,10 +47,6 @@
#include "src/core/lib/gprpp/crash.h"
#include "src/core/lib/gprpp/examine_stack.h"
int gpr_should_log_stacktrace(gpr_log_severity severity);
static long sys_gettid(void) { return syscall(__NR_gettid); }
void gpr_log(const char* file, int line, gpr_log_severity severity,
const char* format, ...) {
// Avoid message construction if gpr_log_message won't log
@ -70,45 +66,4 @@ void gpr_log(const char* file, int line, gpr_log_severity severity,
free(message);
}
void gpr_platform_log(gpr_log_func_args* args) {
const char* final_slash;
const char* display_file;
char time_buffer[64];
time_t timer;
gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
struct tm tm;
static thread_local long tid(0);
if (tid == 0) tid = sys_gettid();
timer = static_cast<time_t>(now.tv_sec);
final_slash = strrchr(args->file, '/');
if (final_slash == nullptr) {
display_file = args->file;
} else {
display_file = final_slash + 1;
}
if (!localtime_r(&timer, &tm)) {
strcpy(time_buffer, "error:localtime");
} else if (0 ==
strftime(time_buffer, sizeof(time_buffer), "%m%d %H:%M:%S", &tm)) {
strcpy(time_buffer, "error:strftime");
}
std::string prefix = absl::StrFormat(
"%s%s.%09" PRId32 " %7ld %s:%d]", gpr_log_severity_string(args->severity),
time_buffer, now.tv_nsec, tid, display_file, args->line);
absl::optional<std::string> stack_trace =
gpr_should_log_stacktrace(args->severity)
? grpc_core::GetCurrentStackTrace()
: absl::nullopt;
if (stack_trace) {
fprintf(stderr, "%-70s %s\n%s\n", prefix.c_str(), args->message,
stack_trace->c_str());
} else {
fprintf(stderr, "%-70s %s\n", prefix.c_str(), args->message);
}
}
#endif // GPR_LINUX_LOG

@ -77,10 +77,6 @@ int gpr_should_log(gpr_log_severity severity) {
}
void gpr_default_log(gpr_log_func_args* args) {
if (!grpc_core::ConfigVars::Get().AbslLogging()) {
gpr_platform_log(args);
return;
}
switch (args->severity) {
case GPR_LOG_SEVERITY_DEBUG:
// Log DEBUG messages as VLOG(2).
@ -99,13 +95,6 @@ void gpr_default_log(gpr_log_func_args* args) {
}
}
int gpr_should_log_stacktrace(gpr_log_severity severity) {
return static_cast<gpr_atm>(severity) >=
gpr_atm_no_barrier_load(&g_min_severity_to_print_stacktrace)
? 1
: 0;
}
void gpr_log_message(const char* file, int line, gpr_log_severity severity,
const char* message) {
if (gpr_should_log(severity) == 0) {

@ -38,10 +38,6 @@
#include "src/core/lib/gprpp/crash.h"
#include "src/core/lib/gprpp/examine_stack.h"
int gpr_should_log_stacktrace(gpr_log_severity severity);
static intptr_t sys_gettid(void) { return (intptr_t)pthread_self(); }
void gpr_log(const char* file, int line, gpr_log_severity severity,
const char* format, ...) {
// Avoid message construction if gpr_log_message won't log
@ -70,42 +66,4 @@ void gpr_log(const char* file, int line, gpr_log_severity severity,
gpr_free(allocated);
}
void gpr_platform_log(gpr_log_func_args* args) {
const char* final_slash;
const char* display_file;
char time_buffer[64];
time_t timer;
gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
struct tm tm;
timer = (time_t)now.tv_sec;
final_slash = strrchr(args->file, '/');
if (final_slash == nullptr)
display_file = args->file;
else
display_file = final_slash + 1;
if (!localtime_r(&timer, &tm)) {
strcpy(time_buffer, "error:localtime");
} else if (0 ==
strftime(time_buffer, sizeof(time_buffer), "%m%d %H:%M:%S", &tm)) {
strcpy(time_buffer, "error:strftime");
}
std::string prefix = absl::StrFormat(
"%s%s.%09d %7" PRIdPTR " %s:%d]", gpr_log_severity_string(args->severity),
time_buffer, (int)(now.tv_nsec), sys_gettid(), display_file, args->line);
absl::optional<std::string> stack_trace =
gpr_should_log_stacktrace(args->severity)
? grpc_core::GetCurrentStackTrace()
: absl::nullopt;
if (stack_trace) {
fprintf(stderr, "%-70s %s\n%s\n", prefix.c_str(), args->message,
stack_trace->c_str());
} else {
fprintf(stderr, "%-70s %s\n", prefix.c_str(), args->message);
}
}
#endif // defined(GPR_POSIX_LOG)

@ -33,8 +33,6 @@
#include "src/core/lib/gprpp/crash.h"
#include "src/core/lib/gprpp/examine_stack.h"
int gpr_should_log_stacktrace(gpr_log_severity severity);
void gpr_log(const char* file, int line, gpr_log_severity severity,
const char* format, ...) {
// Avoid message construction if gpr_log_message won't log
@ -72,45 +70,4 @@ void gpr_log(const char* file, int line, gpr_log_severity severity,
gpr_free(message);
}
// Simple starter implementation
void gpr_platform_log(gpr_log_func_args* args) {
const char* final_slash;
const char* display_file;
char time_buffer[64];
time_t timer;
gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME);
struct tm tm;
timer = (time_t)now.tv_sec;
final_slash = strrchr(args->file, '\\');
if (final_slash == NULL)
display_file = args->file;
else
display_file = final_slash + 1;
if (localtime_s(&tm, &timer)) {
strcpy(time_buffer, "error:localtime");
} else if (0 ==
strftime(time_buffer, sizeof(time_buffer), "%m%d %H:%M:%S", &tm)) {
strcpy(time_buffer, "error:strftime");
}
absl::optional<std::string> stack_trace =
gpr_should_log_stacktrace(args->severity)
? grpc_core::GetCurrentStackTrace()
: absl::nullopt;
if (stack_trace) {
fprintf(stderr, "%s%s.%09u %5lu %s:%d] %s\n%s\n",
gpr_log_severity_string(args->severity), time_buffer,
(int)(now.tv_nsec), GetCurrentThreadId(), display_file, args->line,
args->message, stack_trace->c_str());
} else {
fprintf(stderr, "%s%s.%09u %5lu %s:%d] %s\n",
gpr_log_severity_string(args->severity), time_buffer,
(int)(now.tv_nsec), GetCurrentThreadId(), display_file, args->line,
args->message);
}
fflush(stderr);
}
#endif // GPR_WINDOWS_LOG

@ -0,0 +1,54 @@
// 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.
#include "src/core/lib/gprpp/dump_args.h"
#include "absl/log/check.h"
#include "absl/strings/ascii.h"
#include "absl/strings/string_view.h"
namespace grpc_core {
namespace dump_args_detail {
std::ostream& operator<<(std::ostream& out, const DumpArgs& args) {
// Parse the argument string into a vector of keys.
// #__VA_ARGS__ produces a stringified version of the arguments passed to the
// macro. It's comma separated, and we can use that to split the string into
// keys. Those keys might include parenthesis for e.g. argument lists, and so
// we need to skip commas that are inside parenthesis.
std::vector<absl::string_view> keys;
int depth = 0;
const char* start = args.arg_string_;
for (const char* p = args.arg_string_; *p; ++p) {
if (*p == '(') {
++depth;
} else if (*p == ')') {
--depth;
} else if (*p == ',' && depth == 0) {
keys.push_back(absl::string_view(start, p - start));
start = p + 1;
}
}
keys.push_back(start);
CHECK_EQ(keys.size(), args.arg_dumpers_.size());
for (size_t i = 0; i < keys.size(); i++) {
if (i != 0) out << ", ";
out << absl::StripAsciiWhitespace(keys[i]) << " = ";
args.arg_dumpers_[i](out);
}
return out;
}
} // namespace dump_args_detail
} // namespace grpc_core

@ -0,0 +1,69 @@
// 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_GPRPP_DUMP_ARGS_H
#define GRPC_SRC_CORE_LIB_GPRPP_DUMP_ARGS_H
#include <ostream>
#include <vector>
#include "absl/functional/any_invocable.h"
namespace grpc_core {
namespace dump_args_detail {
// Helper function... just ignore the initializer list passed into it.
// Allows doing 'statements' via parameter pack expansion in C++11 - given
// template <typename... Ts>:
// do_these_things({foo<Ts>()...});
// will execute foo<T>() for each T in Ts.
template <typename T>
void do_these_things(std::initializer_list<T>) {}
class DumpArgs {
public:
template <typename... Args>
explicit DumpArgs(const char* arg_string, const Args&... args)
: arg_string_(arg_string) {
do_these_things(
{AddDumper([a = &args](std::ostream& os) { os << *a; })...});
}
friend std::ostream& operator<<(std::ostream& out, const DumpArgs& args);
private:
int AddDumper(absl::AnyInvocable<void(std::ostream&) const> dumper) {
arg_dumpers_.push_back(std::move(dumper));
return 0;
}
const char* arg_string_;
std::vector<absl::AnyInvocable<void(std::ostream&) const>> arg_dumpers_;
};
} // namespace dump_args_detail
} // namespace grpc_core
// Helper to print a list of variables and their values.
// Each type must be streamable to std::ostream.
// Usage:
// int a = 1;
// int b = 2;
// LOG(INFO) << GRPC_DUMP_ARGS(a, b)
// Output:
// a = 1, b = 2
#define GRPC_DUMP_ARGS(...) \
grpc_core::dump_args_detail::DumpArgs(#__VA_ARGS__, __VA_ARGS__)
#endif // GRPC_SRC_CORE_LIB_GPRPP_DUMP_ARGS_H

@ -41,6 +41,7 @@
#include <string>
#include <vector>
#include "absl/log/log.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
@ -100,14 +101,14 @@ static int epoll_create_and_cloexec() {
#ifdef GRPC_LINUX_EPOLL_CREATE1
int fd = epoll_create1(EPOLL_CLOEXEC);
if (fd < 0) {
gpr_log(GPR_ERROR, "epoll_create1 unavailable");
LOG(ERROR) << "epoll_create1 unavailable";
}
#else
int fd = epoll_create(MAX_EPOLL_EVENTS);
if (fd < 0) {
gpr_log(GPR_ERROR, "epoll_create unavailable");
LOG(ERROR) << "epoll_create unavailable";
} else if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) {
gpr_log(GPR_ERROR, "fcntl following epoll_create failed");
LOG(ERROR) << "fcntl following epoll_create failed";
return -1;
}
#endif
@ -891,7 +892,7 @@ static bool check_neighborhood_for_available_poller(
}
} else {
if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) {
gpr_log(GPR_INFO, " .. beaten to choose next poller");
LOG(INFO) << " .. beaten to choose next poller";
}
}
// even if we didn't win the cas, there's a worker, we can stop
@ -990,7 +991,7 @@ static void end_worker(grpc_pollset* pollset, grpc_pollset_worker* worker,
gpr_cv_destroy(&worker->cv);
}
if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) {
gpr_log(GPR_INFO, " .. remove worker");
LOG(INFO) << " .. remove worker";
}
if (EMPTIED == worker_remove(pollset, worker)) {
pollset_maybe_finish_shutdown(pollset);
@ -1081,7 +1082,7 @@ static grpc_error_handle pollset_kick(grpc_pollset* pollset,
if (root_worker == nullptr) {
pollset->kicked_without_poller = true;
if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) {
gpr_log(GPR_INFO, " .. kicked_without_poller");
LOG(INFO) << " .. kicked_without_poller";
}
goto done;
}
@ -1146,7 +1147,7 @@ static grpc_error_handle pollset_kick(grpc_pollset* pollset,
}
} else {
if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) {
gpr_log(GPR_INFO, " .. kicked while waking up");
LOG(INFO) << " .. kicked while waking up";
}
goto done;
}
@ -1156,7 +1157,7 @@ static grpc_error_handle pollset_kick(grpc_pollset* pollset,
if (specific_worker->state == KICKED) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) {
gpr_log(GPR_INFO, " .. specific worker already kicked");
LOG(INFO) << " .. specific worker already kicked";
}
goto done;
} else if (g_current_thread_worker == specific_worker) {
@ -1169,21 +1170,21 @@ static grpc_error_handle pollset_kick(grpc_pollset* pollset,
reinterpret_cast<grpc_pollset_worker*>(
gpr_atm_no_barrier_load(&g_active_poller))) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) {
gpr_log(GPR_INFO, " .. kick active poller");
LOG(INFO) << " .. kick active poller";
}
SET_KICK_STATE(specific_worker, KICKED);
ret_err = grpc_wakeup_fd_wakeup(&global_wakeup_fd);
goto done;
} else if (specific_worker->initialized_cv) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) {
gpr_log(GPR_INFO, " .. kick waiting worker");
LOG(INFO) << " .. kick waiting worker";
}
SET_KICK_STATE(specific_worker, KICKED);
gpr_cv_signal(&specific_worker->cv);
goto done;
} else {
if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) {
gpr_log(GPR_INFO, " .. kick non-waiting worker");
LOG(INFO) << " .. kick non-waiting worker";
}
SET_KICK_STATE(specific_worker, KICKED);
goto done;
@ -1311,7 +1312,7 @@ static void reset_event_manager_on_fork() {
static bool init_epoll1_linux() {
if (!g_is_shutdown) return true;
if (!grpc_has_wakeup_fd()) {
gpr_log(GPR_ERROR, "Skipping epoll1 because of no wakeup fd.");
LOG(ERROR) << "Skipping epoll1 because of no wakeup fd.";
return false;
}

@ -46,6 +46,7 @@
#include <unordered_map>
#include "absl/log/check.h"
#include "absl/log/log.h"
#include <grpc/slice.h>
#include <grpc/support/alloc.h>
@ -212,7 +213,7 @@ class TcpZerocopySendCtx {
if (send_records_ == nullptr || free_send_records_ == nullptr) {
gpr_free(send_records_);
gpr_free(free_send_records_);
gpr_log(GPR_INFO, "Disabling TCP TX zerocopy due to memory pressure.\n");
LOG(INFO) << "Disabling TCP TX zerocopy due to memory pressure.\n";
memory_limited_ = true;
} else {
for (int idx = 0; idx < max_sends_; ++idx) {
@ -836,7 +837,7 @@ static void tcp_destroy(grpc_endpoint* ep) {
static void perform_reclamation(grpc_tcp* tcp)
ABSL_LOCKS_EXCLUDED(tcp->read_mu) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_resource_quota_trace)) {
gpr_log(GPR_INFO, "TCP: benign reclamation to free memory");
LOG(INFO) << "TCP: benign reclamation to free memory";
}
tcp->read_mu.Lock();
if (tcp->incoming_buffer != nullptr) {
@ -1294,7 +1295,7 @@ static bool tcp_write_with_timestamps(grpc_tcp* tcp, struct msghdr* msg,
if (setsockopt(tcp->fd, SOL_SOCKET, SO_TIMESTAMPING,
static_cast<void*>(&opt), sizeof(opt)) != 0) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) {
gpr_log(GPR_ERROR, "Failed to set timestamping options on the socket.");
LOG(ERROR) << "Failed to set timestamping options on the socket.";
}
return false;
}
@ -1380,7 +1381,7 @@ struct cmsghdr* process_timestamp(grpc_tcp* tcp, msghdr* msg,
cmsghdr* opt_stats = nullptr;
if (next_cmsg == nullptr) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) {
gpr_log(GPR_ERROR, "Received timestamp without extended error");
LOG(ERROR) << "Received timestamp without extended error";
}
return cmsg;
}
@ -1392,7 +1393,7 @@ struct cmsghdr* process_timestamp(grpc_tcp* tcp, msghdr* msg,
next_cmsg = CMSG_NXTHDR(msg, opt_stats);
if (next_cmsg == nullptr) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) {
gpr_log(GPR_ERROR, "Received timestamp without extended error");
LOG(ERROR) << "Received timestamp without extended error";
}
return opt_stats;
}
@ -1402,7 +1403,7 @@ struct cmsghdr* process_timestamp(grpc_tcp* tcp, msghdr* msg,
!(next_cmsg->cmsg_type == IP_RECVERR ||
next_cmsg->cmsg_type == IPV6_RECVERR)) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) {
gpr_log(GPR_ERROR, "Unexpected control message");
LOG(ERROR) << "Unexpected control message";
}
return cmsg;
}
@ -1412,7 +1413,7 @@ struct cmsghdr* process_timestamp(grpc_tcp* tcp, msghdr* msg,
auto serr = reinterpret_cast<struct sock_extended_err*>(CMSG_DATA(next_cmsg));
if (serr->ee_errno != ENOMSG ||
serr->ee_origin != SO_EE_ORIGIN_TIMESTAMPING) {
gpr_log(GPR_ERROR, "Unexpected control message");
LOG(ERROR) << "Unexpected control message";
return cmsg;
}
tcp->tb_list.ProcessTimestamp(serr, opt_stats, tss);
@ -1462,7 +1463,7 @@ static bool process_errors(grpc_tcp* tcp) {
return processed_err;
}
if (GPR_UNLIKELY((msg.msg_flags & MSG_CTRUNC) != 0)) {
gpr_log(GPR_ERROR, "Error message was truncated.");
LOG(ERROR) << "Error message was truncated.";
}
if (msg.msg_controllen == 0) {
@ -1539,14 +1540,14 @@ static bool tcp_write_with_timestamps(grpc_tcp* /*tcp*/, struct msghdr* /*msg*/,
ssize_t* /*sent_length*/,
int* /* saved_errno */,
int /*additional_flags*/) {
gpr_log(GPR_ERROR, "Write with timestamps not supported for this platform");
LOG(ERROR) << "Write with timestamps not supported for this platform";
CHECK(0);
return false;
}
static void tcp_handle_error(void* /*arg*/ /* grpc_tcp */,
grpc_error_handle /*error*/) {
gpr_log(GPR_ERROR, "Error handling is not supported for this platform");
LOG(ERROR) << "Error handling is not supported for this platform";
CHECK(0);
}
#endif // GRPC_LINUX_ERRQUEUE
@ -1842,7 +1843,7 @@ static void tcp_handle_write(void* arg /* grpc_tcp */,
: tcp_flush(tcp, &error);
if (!flush_result) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) {
gpr_log(GPR_INFO, "write: delayed");
LOG(INFO) << "write: delayed";
}
notify_on_write(tcp);
// tcp_flush does not populate error if it has returned false.
@ -1915,7 +1916,7 @@ static void tcp_write(grpc_endpoint* ep, grpc_slice_buffer* buf,
tcp->write_cb = cb;
tcp->current_zerocopy_send = zerocopy_send_record;
if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) {
gpr_log(GPR_INFO, "write: delayed");
LOG(INFO) << "write: delayed";
}
notify_on_write(tcp);
} else {
@ -2029,7 +2030,7 @@ grpc_endpoint* grpc_tcp_create(grpc_fd* em_fd,
if (err == 0) {
tcp->tcp_zerocopy_send_ctx.set_enabled(true);
} else {
gpr_log(GPR_ERROR, "Failed to set zerocopy options on the socket.");
LOG(ERROR) << "Failed to set zerocopy options on the socket.";
}
#endif
}

@ -17,6 +17,7 @@
#include <utility>
#include "absl/functional/any_invocable.h"
#include "absl/meta/type_traits.h"
#include <grpc/support/port_platform.h>
@ -63,6 +64,10 @@ auto WrapInPoll(T&& x) -> decltype(PollWrapper<T>::Wrap(std::forward<T>(x))) {
return PollWrapper<T>::Wrap(std::forward<T>(x));
}
// T -> T, const T& -> T
template <typename T>
using RemoveCVRef = absl::remove_cv_t<absl::remove_reference_t<T>>;
template <typename F, typename SfinaeVoid = void>
class PromiseLike;
@ -73,7 +78,7 @@ template <typename F>
class PromiseLike<F, absl::enable_if_t<!std::is_void<
typename std::result_of<F()>::type>::value>> {
private:
GPR_NO_UNIQUE_ADDRESS F f_;
GPR_NO_UNIQUE_ADDRESS RemoveCVRef<F> f_;
public:
// NOLINTNEXTLINE - internal detail that drastically simplifies calling code.
@ -82,10 +87,6 @@ class PromiseLike<F, absl::enable_if_t<!std::is_void<
using Result = typename PollTraits<decltype(WrapInPoll(f_()))>::Type;
};
// T -> T, const T& -> T
template <typename T>
using RemoveCVRef = absl::remove_cv_t<absl::remove_reference_t<T>>;
} // namespace promise_detail
} // namespace grpc_core

File diff suppressed because it is too large Load Diff

@ -171,6 +171,8 @@ class ValueOrFailure {
T& value() { return value_.value(); }
const T& operator*() const { return *value_; }
T& operator*() { return *value_; }
const T* operator->() const { return &*value_; }
T* operator->() { return &*value_; }
bool operator==(const ValueOrFailure& other) const {
return value_ == other.value_;

@ -42,6 +42,7 @@
#endif
#include "absl/log/check.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/escaping.h"
@ -114,7 +115,7 @@ 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 (!absl::WebSafeBase64Unescape(absl::string_view(str, len), &string)) {
gpr_log(GPR_ERROR, "Invalid base64.");
LOG(ERROR) << "Invalid base64.";
return Json(); // JSON null
}
auto json = grpc_core::JsonParse(string);
@ -163,13 +164,13 @@ static jose_header* jose_header_from_json(Json json) {
Json::Object::const_iterator it;
jose_header* h = grpc_core::Zalloc<jose_header>();
if (json.type() != Json::Type::kObject) {
gpr_log(GPR_ERROR, "JSON value is not an object");
LOG(ERROR) << "JSON value is not an object";
goto error;
}
// Check alg field.
it = json.object().find("alg");
if (it == json.object().end()) {
gpr_log(GPR_ERROR, "Missing alg field.");
LOG(ERROR) << "Missing alg field.";
goto error;
}
// We only support RSA-1.5 signatures for now.
@ -180,7 +181,7 @@ static jose_header* jose_header_from_json(Json json) {
if (it->second.type() != Json::Type::kString ||
strncmp(alg_value, "RS", 2) != 0 ||
evp_md_from_alg(alg_value) == nullptr) {
gpr_log(GPR_ERROR, "Invalid alg field");
LOG(ERROR) << "Invalid alg field";
goto error;
}
h->alg = alg_value;
@ -319,13 +320,13 @@ grpc_jwt_verifier_status grpc_jwt_claims_check(const grpc_jwt_claims* claims,
skewed_now =
gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_clock_skew);
if (gpr_time_cmp(skewed_now, claims->nbf) < 0) {
gpr_log(GPR_ERROR, "JWT is not valid yet.");
LOG(ERROR) << "JWT is not valid yet.";
return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE;
}
skewed_now =
gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), grpc_jwt_verifier_clock_skew);
if (gpr_time_cmp(skewed_now, claims->exp) > 0) {
gpr_log(GPR_ERROR, "JWT is expired.");
LOG(ERROR) << "JWT is expired.";
return GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE;
}
@ -430,7 +431,7 @@ struct grpc_jwt_verifier {
static Json json_from_http(const grpc_http_response* response) {
if (response == nullptr) {
gpr_log(GPR_ERROR, "HTTP response is NULL.");
LOG(ERROR) << "HTTP response is NULL.";
return Json(); // JSON null
}
if (response->status != 200) {
@ -441,7 +442,7 @@ static Json json_from_http(const grpc_http_response* response) {
auto json = grpc_core::JsonParse(
absl::string_view(response->body, response->body_length));
if (!json.ok()) {
gpr_log(GPR_ERROR, "Invalid JSON found in response.");
LOG(ERROR) << "Invalid JSON found in response.";
return Json(); // JSON null
}
return std::move(*json);
@ -464,12 +465,12 @@ static EVP_PKEY* extract_pkey_from_x509(const char* x509_str) {
BIO_write(bio, x509_str, static_cast<int>(len));
x509 = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
if (x509 == nullptr) {
gpr_log(GPR_ERROR, "Unable to parse x509 cert.");
LOG(ERROR) << "Unable to parse x509 cert.";
goto end;
}
result = X509_get_pubkey(x509);
if (result == nullptr) {
gpr_log(GPR_ERROR, "Cannot find public key in X509 cert.");
LOG(ERROR) << "Cannot find public key in X509 cert.";
}
end:
@ -482,7 +483,7 @@ static BIGNUM* bignum_from_base64(const char* b64) {
if (b64 == nullptr) return nullptr;
std::string string;
if (!absl::WebSafeBase64Unescape(b64, &string)) {
gpr_log(GPR_ERROR, "Invalid base64 for big num.");
LOG(ERROR) << "Invalid base64 for big num.";
return nullptr;
}
return BN_bin2bn(reinterpret_cast<const uint8_t*>(string.data()),
@ -540,27 +541,27 @@ static EVP_PKEY* pkey_from_jwk(const Json& json, const char* kty) {
#if OPENSSL_VERSION_NUMBER < 0x30000000L
rsa = RSA_new();
if (rsa == nullptr) {
gpr_log(GPR_ERROR, "Could not create rsa key.");
LOG(ERROR) << "Could not create rsa key.";
goto end;
}
#endif
it = json.object().find("n");
if (it == json.object().end()) {
gpr_log(GPR_ERROR, "Missing RSA public key field.");
LOG(ERROR) << "Missing RSA public key field.";
goto end;
}
tmp_n = bignum_from_base64(validate_string_field(it->second, "n"));
if (tmp_n == nullptr) goto end;
it = json.object().find("e");
if (it == json.object().end()) {
gpr_log(GPR_ERROR, "Missing RSA public key field.");
LOG(ERROR) << "Missing RSA public key field.";
goto end;
}
tmp_e = bignum_from_base64(validate_string_field(it->second, "e"));
if (tmp_e == nullptr) goto end;
#if OPENSSL_VERSION_NUMBER < 0x30000000L
if (!RSA_set0_key(rsa, tmp_n, tmp_e, nullptr)) {
gpr_log(GPR_ERROR, "Cannot set RSA key from inputs.");
LOG(ERROR) << "Cannot set RSA key from inputs.";
goto end;
}
// RSA_set0_key takes ownership on success.
@ -573,21 +574,21 @@ static EVP_PKEY* pkey_from_jwk(const Json& json, const char* kty) {
if (!OSSL_PARAM_BLD_push_BN(bld, "n", tmp_n) ||
!OSSL_PARAM_BLD_push_BN(bld, "e", tmp_e) ||
(params = OSSL_PARAM_BLD_to_param(bld)) == NULL) {
gpr_log(GPR_ERROR, "Could not create OSSL_PARAM");
LOG(ERROR) << "Could not create OSSL_PARAM";
goto end;
}
ctx = EVP_PKEY_CTX_new_from_name(nullptr, "RSA", nullptr);
if (ctx == nullptr) {
gpr_log(GPR_ERROR, "Could not create rsa key.");
LOG(ERROR) << "Could not create rsa key.";
goto end;
}
if (EVP_PKEY_fromdata_init(ctx) <= 0) {
gpr_log(GPR_ERROR, "Could not create rsa key.");
LOG(ERROR) << "Could not create rsa key.";
goto end;
}
if (EVP_PKEY_fromdata(ctx, &result, EVP_PKEY_KEYPAIR, params) <= 0) {
gpr_log(GPR_ERROR, "Cannot set RSA key from inputs.");
LOG(ERROR) << "Cannot set RSA key from inputs.";
goto end;
}
#endif
@ -618,8 +619,7 @@ static EVP_PKEY* find_verification_key(const Json& json, const char* header_alg,
return extract_pkey_from_x509(cur->string().c_str());
}
if (jwt_keys->type() != Json::Type::kArray) {
gpr_log(GPR_ERROR,
"Unexpected value type of keys property in jwks key set.");
LOG(ERROR) << "Unexpected value type of keys property in jwks key set.";
return nullptr;
}
// Key format is specified in:
@ -661,21 +661,21 @@ static int verify_jwt_signature(EVP_PKEY* key, const char* alg,
CHECK_NE(md, nullptr); // Checked before.
if (md_ctx == nullptr) {
gpr_log(GPR_ERROR, "Could not create EVP_MD_CTX.");
LOG(ERROR) << "Could not create EVP_MD_CTX.";
goto end;
}
if (EVP_DigestVerifyInit(md_ctx, nullptr, md, nullptr, key) != 1) {
gpr_log(GPR_ERROR, "EVP_DigestVerifyInit failed.");
LOG(ERROR) << "EVP_DigestVerifyInit failed.";
goto end;
}
if (EVP_DigestVerifyUpdate(md_ctx, GRPC_SLICE_START_PTR(signed_data),
GRPC_SLICE_LENGTH(signed_data)) != 1) {
gpr_log(GPR_ERROR, "EVP_DigestVerifyUpdate failed.");
LOG(ERROR) << "EVP_DigestVerifyUpdate failed.";
goto end;
}
if (EVP_DigestVerifyFinal(md_ctx, GRPC_SLICE_START_PTR(signature),
GRPC_SLICE_LENGTH(signature)) != 1) {
gpr_log(GPR_ERROR, "JWT signature verification failed.");
LOG(ERROR) << "JWT signature verification failed.";
goto end;
}
@ -742,7 +742,7 @@ static void on_openid_config_retrieved(void* user_data,
if (json.type() == Json::Type::kNull) goto error;
cur = find_property_by_name(json, "jwks_uri");
if (cur == nullptr) {
gpr_log(GPR_ERROR, "Could not find jwks_uri in openid config.");
LOG(ERROR) << "Could not find jwks_uri in openid config.";
goto error;
}
jwks_uri = validate_string_field(*cur, "jwks_uri");
@ -843,11 +843,11 @@ static void retrieve_key_and_verify(verifier_cb_ctx* ctx) {
CHECK(ctx != nullptr && ctx->header != nullptr && ctx->claims != nullptr);
iss = ctx->claims->iss;
if (ctx->header->kid == nullptr) {
gpr_log(GPR_ERROR, "Missing kid in jose header.");
LOG(ERROR) << "Missing kid in jose header.";
goto error;
}
if (iss == nullptr) {
gpr_log(GPR_ERROR, "Missing iss in claims.");
LOG(ERROR) << "Missing iss in claims.";
goto error;
}
@ -862,7 +862,7 @@ static void retrieve_key_and_verify(verifier_cb_ctx* ctx) {
CHECK_NE(ctx->verifier, nullptr);
mapping = verifier_get_mapping(ctx->verifier, email_domain);
if (mapping == nullptr) {
gpr_log(GPR_ERROR, "Missing mapping for issuer email.");
LOG(ERROR) << "Missing mapping for issuer email.";
goto error;
}
host = gpr_strdup(mapping->key_url_prefix);

File diff suppressed because it is too large Load Diff

@ -82,7 +82,7 @@ class Call : public CppImplOf<Call, grpc_call>,
public grpc_event_engine::experimental::EventEngine::
Closure /* for deadlines */ {
public:
Arena* arena() { return arena_; }
virtual Arena* arena() = 0;
bool is_client() const { return is_client_; }
virtual void ContextSet(grpc_context_index elem, void* value,
@ -92,7 +92,7 @@ class Call : public CppImplOf<Call, grpc_call>,
void CancelWithStatus(grpc_status_code status, const char* description);
virtual void CancelWithError(grpc_error_handle error) = 0;
virtual void SetCompletionQueue(grpc_completion_queue* cq) = 0;
char* GetPeer();
virtual char* GetPeer() = 0;
virtual grpc_call_error StartBatch(const grpc_op* ops, size_t nops,
void* notify_tag,
bool is_notify_tag_closure) = 0;
@ -157,25 +157,15 @@ class Call : public CppImplOf<Call, grpc_call>,
Call* sibling_prev = nullptr;
};
Call(Arena* arena, bool is_client, Timestamp send_deadline,
RefCountedPtr<Channel> channel)
: channel_(std::move(channel)),
arena_(arena),
send_deadline_(send_deadline),
is_client_(is_client) {
DCHECK_NE(arena_, nullptr);
DCHECK(channel_ != nullptr);
}
Call(bool is_client, Timestamp send_deadline,
grpc_event_engine::experimental::EventEngine* event_engine)
: send_deadline_(send_deadline),
is_client_(is_client),
event_engine_(event_engine) {}
~Call() override = default;
void DeleteThis();
ParentCall* GetOrCreateParentCall();
ParentCall* parent_call();
Channel* channel() const {
DCHECK(channel_ != nullptr);
return channel_.get();
}
absl::Status InitParent(Call* parent, uint32_t propagation_mask);
void PublishToParent(Call* parent);
@ -221,9 +211,9 @@ class Call : public CppImplOf<Call, grpc_call>,
gpr_cycle_counter start_time() const { return start_time_; }
virtual grpc_compression_options compression_options() = 0;
private:
RefCountedPtr<Channel> channel_;
Arena* const arena_;
std::atomic<ParentCall*> parent_call_{nullptr};
ChildCall* child_ = nullptr;
Timestamp send_deadline_;
@ -247,34 +237,13 @@ class Call : public CppImplOf<Call, grpc_call>,
Timestamp deadline_ ABSL_GUARDED_BY(deadline_mu_) = Timestamp::InfFuture();
grpc_event_engine::experimental::EventEngine::TaskHandle ABSL_GUARDED_BY(
deadline_mu_) deadline_task_;
grpc_event_engine::experimental::EventEngine* const event_engine_;
gpr_cycle_counter start_time_ = gpr_get_cycle_counter();
};
class BasicPromiseBasedCall;
class ServerPromiseBasedCall;
class ServerCallContext {
public:
virtual void PublishInitialMetadata(
ClientMetadataHandle metadata,
grpc_metadata_array* publish_initial_metadata) = 0;
// Construct the top of the server call promise for the v2 filter stack.
// TODO(ctiller): delete when v3 is available.
virtual ArenaPromise<ServerMetadataHandle> MakeTopOfServerCallPromise(
CallArgs call_args, grpc_completion_queue* cq,
absl::FunctionRef<void(grpc_call* call)> publish) = 0;
// Server stream data as supplied by the transport (so we can link the
// transport stream up with the call again).
// TODO(ctiller): legacy API - once we move transports to promises we'll
// create the promise directly and not need to pass around this token.
virtual const void* server_stream_data() = 0;
protected:
~ServerCallContext() = default;
};
// TODO(ctiller): move more call things into this type
class CallContext {
public:
@ -300,8 +269,6 @@ class CallContext {
gpr_atm* peer_string_atm_ptr();
gpr_cycle_counter call_start_time() { return start_time_; }
ServerCallContext* server_call_context();
void set_traced(bool traced) { traced_ = traced; }
bool traced() const { return traced_; }
@ -329,9 +296,10 @@ template <>
struct ContextType<CallContext> {};
// TODO(ctiller): remove once call-v3 finalized
RefCountedPtr<CallSpineInterface> MakeServerCall(
ClientMetadataHandle client_initial_metadata, ServerInterface* server,
Channel* channel, Arena* arena);
grpc_call* MakeServerCall(CallHandler call_handler,
ClientMetadataHandle client_initial_metadata,
ServerInterface* server, grpc_completion_queue* cq,
grpc_metadata_array* publish_initial_metadata);
} // namespace grpc_core

@ -104,9 +104,9 @@ ChannelInit::FilterRegistration::ExcludeFromMinimalStack() {
ChannelInit::FilterRegistration& ChannelInit::Builder::RegisterFilter(
grpc_channel_stack_type type, const grpc_channel_filter* filter,
const ChannelFilterVtable* vtable, SourceLocation registration_source) {
FilterAdder filter_adder, SourceLocation registration_source) {
filters_[type].emplace_back(std::make_unique<FilterRegistration>(
filter, vtable, registration_source));
filter, filter_adder, registration_source));
return *filters_[type].back();
}
@ -223,9 +223,10 @@ ChannelInit::StackConfig ChannelInit::BuildStackConfig(
while (!dependencies.empty()) {
auto filter = take_ready_dependency();
auto* registration = filter_to_registration[filter];
filters.emplace_back(
filter, registration->vtable_, std::move(registration->predicates_),
registration->skip_v3_, registration->registration_source_);
filters.emplace_back(filter, registration->filter_adder_,
std::move(registration->predicates_),
registration->skip_v3_,
registration->registration_source_);
for (auto& p : dependencies) {
p.second.erase(filter);
}
@ -406,78 +407,21 @@ bool ChannelInit::CreateStack(ChannelStackBuilder* builder) const {
return true;
}
absl::StatusOr<ChannelInit::StackSegment> ChannelInit::CreateStackSegment(
grpc_channel_stack_type type, const ChannelArgs& args) const {
void ChannelInit::AddToInterceptionChainBuilder(
grpc_channel_stack_type type, InterceptionChainBuilder& builder) const {
const auto& stack_config = stack_configs_[type];
std::vector<StackSegment::ChannelFilter> filters;
size_t channel_data_size = 0;
size_t channel_data_alignment = 0;
// Based on predicates build a list of filters to include in this segment.
for (const auto& filter : stack_config.filters) {
if (filter.skip_v3) continue;
if (!filter.CheckPredicates(args)) continue;
if (filter.vtable == nullptr) {
return absl::InvalidArgumentError(
if (!filter.CheckPredicates(builder.channel_args())) continue;
if (filter.filter_adder == nullptr) {
builder.Fail(absl::InvalidArgumentError(
absl::StrCat("Filter ", NameFromChannelFilter(filter.filter),
" has no v3-callstack vtable"));
" has no v3-callstack vtable")));
return;
}
channel_data_alignment =
std::max(channel_data_alignment, filter.vtable->alignment);
if (channel_data_size % filter.vtable->alignment != 0) {
channel_data_size += filter.vtable->alignment -
(channel_data_size % filter.vtable->alignment);
}
filters.push_back({channel_data_size, filter.vtable});
channel_data_size += filter.vtable->size;
}
// Shortcut for empty segments.
if (filters.empty()) return StackSegment();
// Allocate memory for the channel data, initialize channel filters into it.
uint8_t* p = static_cast<uint8_t*>(
gpr_malloc_aligned(channel_data_size, channel_data_alignment));
for (size_t i = 0; i < filters.size(); i++) {
auto r = filters[i].vtable->init(p + filters[i].offset, args);
if (!r.ok()) {
for (size_t j = 0; j < i; j++) {
filters[j].vtable->destroy(p + filters[j].offset);
}
gpr_free_aligned(p);
return r;
}
}
return StackSegment(std::move(filters), p);
}
///////////////////////////////////////////////////////////////////////////////
// ChannelInit::StackSegment
ChannelInit::StackSegment::StackSegment(std::vector<ChannelFilter> filters,
uint8_t* channel_data)
: data_(MakeRefCounted<ChannelData>(std::move(filters), channel_data)) {}
void ChannelInit::StackSegment::AddToCallFilterStack(
CallFilters::StackBuilder& builder) {
if (data_ == nullptr) return;
data_->AddToCallFilterStack(builder);
builder.AddOwnedObject(data_);
};
ChannelInit::StackSegment::ChannelData::ChannelData(
std::vector<ChannelFilter> filters, uint8_t* channel_data)
: filters_(std::move(filters)), channel_data_(channel_data) {}
void ChannelInit::StackSegment::ChannelData::AddToCallFilterStack(
CallFilters::StackBuilder& builder) {
for (const auto& filter : filters_) {
filter.vtable->add_to_stack_builder(channel_data_ + filter.offset, builder);
}
}
ChannelInit::StackSegment::ChannelData::~ChannelData() {
for (const auto& filter : filters_) {
filter.vtable->destroy(channel_data_ + filter.offset);
filter.filter_adder(builder);
}
gpr_free_aligned(channel_data_);
}
} // namespace grpc_core

@ -38,6 +38,7 @@
#include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/surface/channel_stack_type.h"
#include "src/core/lib/transport/call_filters.h"
#include "src/core/lib/transport/interception_chain.h"
/// This module provides a way for plugins (and the grpc core library itself)
/// to register mutators for channel stacks.
@ -68,6 +69,8 @@ class ChannelInit {
using InclusionPredicate = absl::AnyInvocable<bool(const ChannelArgs&) const>;
// Post processor for the channel stack - applied in PostProcessorSlot order
using PostProcessor = absl::AnyInvocable<void(ChannelStackBuilder&) const>;
// Function that can be called to add a filter to a stack builder
using FilterAdder = void (*)(InterceptionChainBuilder&);
// Post processing slots - up to one PostProcessor per slot can be registered
// They run after filters registered are added to the channel stack builder,
// but before Build is called - allowing ad-hoc mutation to the channel stack.
@ -77,25 +80,15 @@ class ChannelInit {
kCount
};
// Vtable-like data structure for channel data initialization
struct ChannelFilterVtable {
size_t size;
size_t alignment;
absl::Status (*init)(void* data, const ChannelArgs& args);
void (*destroy)(void* data);
void (*add_to_stack_builder)(void* data,
CallFilters::StackBuilder& builder);
};
class FilterRegistration {
public:
// TODO(ctiller): Remove grpc_channel_filter* arg when that can be
// deprecated (once filter stack is removed).
explicit FilterRegistration(const grpc_channel_filter* filter,
const ChannelFilterVtable* vtable,
FilterAdder filter_adder,
SourceLocation registration_source)
: filter_(filter),
vtable_(vtable),
filter_adder_(filter_adder),
registration_source_(registration_source) {}
FilterRegistration(const FilterRegistration&) = delete;
FilterRegistration& operator=(const FilterRegistration&) = delete;
@ -170,7 +163,7 @@ class ChannelInit {
private:
friend class ChannelInit;
const grpc_channel_filter* const filter_;
const ChannelFilterVtable* const vtable_;
const FilterAdder filter_adder_;
std::vector<const grpc_channel_filter*> after_;
std::vector<const grpc_channel_filter*> before_;
std::vector<InclusionPredicate> predicates_;
@ -188,16 +181,17 @@ class ChannelInit {
// properties of the filter being registered.
// TODO(ctiller): remove in favor of the version that does not mention
// grpc_channel_filter
FilterRegistration& RegisterFilter(
grpc_channel_stack_type type, const grpc_channel_filter* filter,
const ChannelFilterVtable* vtable = nullptr,
SourceLocation registration_source = {});
FilterRegistration& RegisterFilter(grpc_channel_stack_type type,
const grpc_channel_filter* filter,
FilterAdder filter_adder = nullptr,
SourceLocation registration_source = {});
template <typename Filter>
FilterRegistration& RegisterFilter(
grpc_channel_stack_type type, SourceLocation registration_source = {}) {
return RegisterFilter(type, &Filter::kFilter,
VtableForType<Filter>::vtable(),
registration_source);
return RegisterFilter(
type, &Filter::kFilter,
[](InterceptionChainBuilder& builder) { builder.Add<Filter>(); },
registration_source);
}
// Filter does not participate in v3
@ -232,58 +226,13 @@ class ChannelInit {
[static_cast<int>(PostProcessorSlot::kCount)];
};
// A set of channel filters that can be added to a call stack.
// TODO(ctiller): move this out so it can be used independently of
// the global registration mechanisms.
class StackSegment final {
public:
// Registration of one channel filter in the stack.
struct ChannelFilter {
size_t offset;
const ChannelFilterVtable* vtable;
};
StackSegment() = default;
explicit StackSegment(std::vector<ChannelFilter> filters,
uint8_t* channel_data);
StackSegment(const StackSegment& other) = delete;
StackSegment& operator=(const StackSegment& other) = delete;
StackSegment(StackSegment&& other) noexcept = default;
StackSegment& operator=(StackSegment&& other) = default;
// Add this segment to a call filter stack builder
void AddToCallFilterStack(CallFilters::StackBuilder& builder);
private:
// Combined channel data for the stack
class ChannelData : public RefCounted<ChannelData> {
public:
explicit ChannelData(std::vector<ChannelFilter> filters,
uint8_t* channel_data);
~ChannelData() override;
void AddToCallFilterStack(CallFilters::StackBuilder& builder);
private:
std::vector<ChannelFilter> filters_;
uint8_t* channel_data_;
};
RefCountedPtr<ChannelData> data_;
};
/// Construct a channel stack of some sort: see channel_stack.h for details
/// \a builder is the channel stack builder to build into.
GRPC_MUST_USE_RESULT
bool CreateStack(ChannelStackBuilder* builder) const;
// Create a segment of a channel stack.
// Terminators and post processors are not included in this construction:
// terminators are a legacy filter-stack concept, and post processors
// need to migrate to other mechanisms.
// TODO(ctiller): figure out other mechanisms.
absl::StatusOr<StackSegment> CreateStackSegment(
grpc_channel_stack_type type, const ChannelArgs& args) const;
void AddToInterceptionChainBuilder(grpc_channel_stack_type type,
InterceptionChainBuilder& builder) const;
private:
// The type of object returned by a filter's Create method.
@ -292,16 +241,16 @@ class ChannelInit {
typename decltype(T::Create(ChannelArgs(), {}))::value_type;
struct Filter {
Filter(const grpc_channel_filter* filter, const ChannelFilterVtable* vtable,
Filter(const grpc_channel_filter* filter, FilterAdder filter_adder,
std::vector<InclusionPredicate> predicates, bool skip_v3,
SourceLocation registration_source)
: filter(filter),
vtable(vtable),
filter_adder(filter_adder),
predicates(std::move(predicates)),
registration_source(registration_source),
skip_v3(skip_v3) {}
const grpc_channel_filter* filter;
const ChannelFilterVtable* vtable;
const FilterAdder filter_adder;
std::vector<InclusionPredicate> predicates;
SourceLocation registration_source;
bool skip_v3 = false;
@ -313,17 +262,6 @@ class ChannelInit {
std::vector<PostProcessor> post_processors;
};
template <typename T, typename = void>
struct VtableForType {
static const ChannelFilterVtable* vtable() { return nullptr; }
};
template <typename T>
struct VtableForType<T, absl::void_t<typename T::Call>> {
static const ChannelFilterVtable kVtable;
static const ChannelFilterVtable* vtable() { return &kVtable; }
};
StackConfig stack_configs_[GRPC_NUM_CHANNEL_STACK_TYPES];
static StackConfig BuildStackConfig(
@ -331,22 +269,6 @@ class ChannelInit {
PostProcessor* post_processors, grpc_channel_stack_type type);
};
template <typename T>
const ChannelInit::ChannelFilterVtable
ChannelInit::VtableForType<T, absl::void_t<typename T::Call>>::kVtable = {
sizeof(CreatedType<T>), alignof(CreatedType<T>),
[](void* data, const ChannelArgs& args) -> absl::Status {
// TODO(ctiller): fill in ChannelFilter::Args (2nd arg)
absl::StatusOr<CreatedType<T>> r = T::Create(args, {});
if (!r.ok()) return r.status();
new (data) CreatedType<T>(std::move(*r));
return absl::OkStatus();
},
[](void* data) { Destruct(static_cast<CreatedType<T>*>(data)); },
[](void* data, CallFilters::StackBuilder& builder) {
builder.Add(static_cast<CreatedType<T>*>(data)->get());
}};
} // namespace grpc_core
#endif // GRPC_SRC_CORE_LIB_SURFACE_CHANNEL_INIT_H

@ -66,10 +66,10 @@ static bool g_shutting_down ABSL_GUARDED_BY(g_init_mu) = false;
namespace grpc_core {
void RegisterSecurityFilters(CoreConfiguration::Builder* builder) {
builder->channel_init()
->RegisterFilter<ClientAuthFilter>(GRPC_CLIENT_SUBCHANNEL)
->RegisterV2Filter<ClientAuthFilter>(GRPC_CLIENT_SUBCHANNEL)
.IfHasChannelArg(GRPC_ARG_SECURITY_CONNECTOR);
builder->channel_init()
->RegisterFilter<ClientAuthFilter>(GRPC_CLIENT_DIRECT_CHANNEL)
->RegisterV2Filter<ClientAuthFilter>(GRPC_CLIENT_DIRECT_CHANNEL)
.IfHasChannelArg(GRPC_ARG_SECURITY_CONNECTOR);
builder->channel_init()
->RegisterFilter<ServerAuthFilter>(GRPC_SERVER_CHANNEL)

@ -51,6 +51,24 @@ class CallDestination : public DualRefCounted<CallDestination> {
virtual void HandleCall(CallHandler unstarted_call_handler) = 0;
};
template <typename HC>
auto MakeCallDestinationFromHandlerFunction(HC handle_call) {
class Impl : public CallDestination {
public:
explicit Impl(HC handle_call) : handle_call_(std::move(handle_call)) {}
void Orphaned() override {}
void HandleCall(CallHandler call_handler) override {
handle_call_(std::move(call_handler));
}
private:
HC handle_call_;
};
return MakeRefCounted<Impl>(std::move(handle_call));
}
} // namespace grpc_core
#endif // GRPC_SRC_CORE_LIB_TRANSPORT_CALL_DESTINATION_H

@ -1245,6 +1245,42 @@ const NoInterceptor
template <typename Fn>
const NoInterceptor ServerTrailingMetadataInterceptor<Fn>::Call::OnFinalize;
template <typename Fn>
class ClientInitialMetadataInterceptor {
public:
class Call {
public:
auto OnClientInitialMetadata(ClientMetadata& md,
ClientInitialMetadataInterceptor* filter) {
return filter->fn_(md);
}
static const NoInterceptor OnServerInitialMetadata;
static const NoInterceptor OnClientToServerMessage;
static const NoInterceptor OnServerToClientMessage;
static const NoInterceptor OnServerTrailingMetadata;
static const NoInterceptor OnFinalize;
};
explicit ClientInitialMetadataInterceptor(Fn fn) : fn_(std::move(fn)) {}
private:
GPR_NO_UNIQUE_ADDRESS Fn fn_;
};
template <typename Fn>
const NoInterceptor
ClientInitialMetadataInterceptor<Fn>::Call::OnServerInitialMetadata;
template <typename Fn>
const NoInterceptor
ClientInitialMetadataInterceptor<Fn>::Call::OnClientToServerMessage;
template <typename Fn>
const NoInterceptor
ClientInitialMetadataInterceptor<Fn>::Call::OnServerToClientMessage;
template <typename Fn>
const NoInterceptor
ClientInitialMetadataInterceptor<Fn>::Call::OnServerTrailingMetadata;
template <typename Fn>
const NoInterceptor ClientInitialMetadataInterceptor<Fn>::Call::OnFinalize;
} // namespace filters_detail
// Execution environment for a stack of filters.
@ -1302,6 +1338,14 @@ class CallFilters {
AddOwnedObject([](void* p) { delete static_cast<T*>(p); }, p.release());
}
template <typename Fn>
void AddOnClientInitialMetadata(Fn fn) {
auto filter = std::make_unique<
filters_detail::ClientInitialMetadataInterceptor<Fn>>(std::move(fn));
Add(filter.get());
AddOwnedObject(std::move(filter));
}
template <typename Fn>
void AddOnServerTrailingMetadata(Fn fn) {
auto filter = std::make_unique<

@ -518,6 +518,8 @@ class CallHandler {
auto PullMessage() { return spine_->PullClientToServerMessage(); }
auto WasCancelled() { return spine_->WasCancelled(); }
template <typename PromiseFactory>
void SpawnGuarded(absl::string_view name, PromiseFactory promise_factory,
DebugLocation whence = {}) {
@ -536,11 +538,15 @@ class CallHandler {
Arena* arena() { return spine_->arena(); }
grpc_event_engine::experimental::EventEngine* event_engine() {
grpc_event_engine::experimental::EventEngine* event_engine() const {
return DownCast<CallSpine*>(spine_.get())->event_engine();
}
// TODO(ctiller): re-evaluate this API
const grpc_call_context_element* legacy_context() const {
return DownCast<CallSpine*>(spine_.get())->legacy_context();
}
grpc_call_context_element* legacy_context() {
return DownCast<CallSpine*>(spine_.get())->legacy_context();
}

@ -175,12 +175,23 @@ class InterceptionChainBuilder final {
return *this;
};
// Add a filter that just mutates client initial metadata.
template <typename F>
void AddOnClientInitialMetadata(F f) {
stack_builder().AddOnClientInitialMetadata(std::move(f));
}
// Add a filter that just mutates server trailing metadata.
template <typename F>
void AddOnServerTrailingMetadata(F f) {
stack_builder().AddOnServerTrailingMetadata(std::move(f));
}
void Fail(absl::Status status) {
CHECK(!status.ok()) << status;
if (status_.ok()) status_ = std::move(status);
}
// Build this stack
absl::StatusOr<RefCountedPtr<UnstartedCallDestination>> Build(
FinalDestination final_destination);

@ -55,6 +55,7 @@
#include "src/core/lib/promise/pipe.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/slice/slice_buffer.h"
#include "src/core/lib/transport/call_destination.h"
#include "src/core/lib/transport/call_final_info.h"
#include "src/core/lib/transport/call_spine.h"
#include "src/core/lib/transport/connectivity_state.h"
@ -481,6 +482,15 @@ typedef struct grpc_transport_op {
grpc_handler_private_op_data handler_private;
} grpc_transport_op;
// Allocate a grpc_transport_op, and preconfigure the on_complete closure to
// \a on_complete and then delete the returned transport op
grpc_transport_op* grpc_make_transport_op(grpc_closure* on_complete);
// Allocate a grpc_transport_stream_op_batch, and preconfigure the on_complete
// closure
// to \a on_complete and then delete the returned transport op
grpc_transport_stream_op_batch* grpc_make_transport_stream_op(
grpc_closure* on_complete);
void grpc_transport_stream_op_batch_finish_with_failure(
grpc_transport_stream_op_batch* batch, grpc_error_handle error,
grpc_core::CallCombiner* call_combiner);
@ -507,6 +517,21 @@ class Transport : public InternallyRefCounted<Transport> {
struct RawPointerChannelArgTag {};
static absl::string_view ChannelArgName() { return GRPC_ARG_TRANSPORT; }
// Though internally ref counted transports expose their "Ref" method to
// create a RefCountedPtr to themselves. The OrphanablePtr owner is the
// singleton decision maker on whether the transport should be destroyed or
// not.
// TODO(ctiller): consider moving to a DualRefCounted model (with the
// disadvantage that we would accidentally have many strong owners which is
// unnecessary for this type).
RefCountedPtr<Transport> Ref() {
return InternallyRefCounted<Transport>::Ref();
}
template <typename T>
RefCountedPtr<T> RefAsSubclass() {
return InternallyRefCounted<Transport>::RefAsSubclass<T>();
}
virtual FilterStackTransport* filter_stack_transport() = 0;
virtual ClientTransport* client_transport() = 0;
virtual ServerTransport* server_transport() = 0;
@ -527,6 +552,20 @@ class Transport : public InternallyRefCounted<Transport> {
// implementation of grpc_transport_perform_op
virtual void PerformOp(grpc_transport_op* op) = 0;
void StartConnectivityWatch(
OrphanablePtr<ConnectivityStateWatcherInterface> watcher) {
grpc_transport_op* op = grpc_make_transport_op(nullptr);
op->start_connectivity_watch = std::move(watcher);
PerformOp(op);
}
void DisconnectWithError(grpc_error_handle error) {
CHECK(!error.ok()) << error;
grpc_transport_op* op = grpc_make_transport_op(nullptr);
op->disconnect_with_error = error;
PerformOp(op);
}
// implementation of grpc_transport_get_endpoint
virtual grpc_endpoint* GetEndpoint() = 0;
};
@ -582,24 +621,9 @@ class ClientTransport : public Transport {
class ServerTransport : public Transport {
public:
// Acceptor helps transports create calls.
class Acceptor {
public:
// Returns an arena that can be used to allocate memory for initial metadata
// parsing, and later passed to CreateCall() as the underlying arena for
// that call.
virtual Arena* CreateArena() = 0;
// Create a call at the server (or fail)
// arena must have been previously allocated by CreateArena()
virtual absl::StatusOr<CallInitiator> CreateCall(
ClientMetadataHandle client_initial_metadata, Arena* arena) = 0;
protected:
~Acceptor() = default;
};
// Called once slightly after transport setup to register the accept function.
virtual void SetAcceptor(Acceptor* acceptor) = 0;
virtual void SetCallDestination(
RefCountedPtr<UnstartedCallDestination> unstarted_call_handler) = 0;
protected:
~ServerTransport() override = default;
@ -607,15 +631,6 @@ class ServerTransport : public Transport {
} // namespace grpc_core
// Allocate a grpc_transport_op, and preconfigure the on_complete closure to
// \a on_complete and then delete the returned transport op
grpc_transport_op* grpc_make_transport_op(grpc_closure* on_complete);
// Allocate a grpc_transport_stream_op_batch, and preconfigure the on_complete
// closure
// to \a on_complete and then delete the returned transport op
grpc_transport_stream_op_batch* grpc_make_transport_stream_op(
grpc_closure* on_complete);
namespace grpc_core {
// This is the key to be used for loading/storing keepalive_throttling in the
// absl::Status object.

@ -84,19 +84,25 @@ const auto kMetricDisconnections =
"grpc.lb.pick_first.disconnections",
"EXPERIMENTAL. Number of times the selected subchannel becomes "
"disconnected.",
"{disconnection}", {kMetricLabelTarget}, {}, false);
"{disconnection}", false)
.Labels(kMetricLabelTarget)
.Build();
const auto kMetricConnectionAttemptsSucceeded =
GlobalInstrumentsRegistry::RegisterUInt64Counter(
"grpc.lb.pick_first.connection_attempts_succeeded",
"EXPERIMENTAL. Number of successful connection attempts.", "{attempt}",
{kMetricLabelTarget}, {}, false);
false)
.Labels(kMetricLabelTarget)
.Build();
const auto kMetricConnectionAttemptsFailed =
GlobalInstrumentsRegistry::RegisterUInt64Counter(
"grpc.lb.pick_first.connection_attempts_failed",
"EXPERIMENTAL. Number of failed connection attempts.", "{attempt}",
{kMetricLabelTarget}, {}, false);
false)
.Labels(kMetricLabelTarget)
.Build();
class PickFirstConfig final : public LoadBalancingPolicy::Config {
public:

@ -128,26 +128,27 @@ constexpr absl::string_view kMetricLabelPickResult = "grpc.lb.pick_result";
const auto kMetricCacheSize =
GlobalInstrumentsRegistry::RegisterCallbackInt64Gauge(
"grpc.lb.rls.cache_size", "EXPERIMENTAL. Size of the RLS cache.", "By",
{kMetricLabelTarget, kMetricLabelRlsServerTarget,
kMetricLabelRlsInstanceUuid},
{}, false);
false)
.Labels(kMetricLabelTarget, kMetricLabelRlsServerTarget,
kMetricLabelRlsInstanceUuid)
.Build();
const auto kMetricCacheEntries =
GlobalInstrumentsRegistry::RegisterCallbackInt64Gauge(
"grpc.lb.rls.cache_entries",
"EXPERIMENTAL. Number of entries in the RLS cache.", "{entry}",
{kMetricLabelTarget, kMetricLabelRlsServerTarget,
kMetricLabelRlsInstanceUuid},
{}, false);
"EXPERIMENTAL. Number of entries in the RLS cache.", "{entry}", false)
.Labels(kMetricLabelTarget, kMetricLabelRlsServerTarget,
kMetricLabelRlsInstanceUuid)
.Build();
const auto kMetricDefaultTargetPicks =
GlobalInstrumentsRegistry::RegisterUInt64Counter(
"grpc.lb.rls.default_target_picks",
"EXPERIMENTAL. Number of LB picks sent to the default target.",
"{pick}",
{kMetricLabelTarget, kMetricLabelRlsServerTarget,
kMetricRlsDataPlaneTarget, kMetricLabelPickResult},
{}, false);
"{pick}", false)
.Labels(kMetricLabelTarget, kMetricLabelRlsServerTarget,
kMetricRlsDataPlaneTarget, kMetricLabelPickResult)
.Build();
const auto kMetricTargetPicks =
GlobalInstrumentsRegistry::RegisterUInt64Counter(
@ -156,17 +157,19 @@ const auto kMetricTargetPicks =
"if the default target is also returned by the RLS server, RPCs sent "
"to that target from the cache will be counted in this metric, not "
"in grpc.rls.default_target_picks.",
"{pick}",
{kMetricLabelTarget, kMetricLabelRlsServerTarget,
kMetricRlsDataPlaneTarget, kMetricLabelPickResult},
{}, false);
"{pick}", false)
.Labels(kMetricLabelTarget, kMetricLabelRlsServerTarget,
kMetricRlsDataPlaneTarget, kMetricLabelPickResult)
.Build();
const auto kMetricFailedPicks =
GlobalInstrumentsRegistry::RegisterUInt64Counter(
"grpc.lb.rls.failed_picks",
"EXPERIMENTAL. Number of LB picks failed due to either a failed RLS "
"request or the RLS channel being throttled.",
"{pick}", {kMetricLabelTarget, kMetricLabelRlsServerTarget}, {}, false);
"{pick}", false)
.Labels(kMetricLabelTarget, kMetricLabelRlsServerTarget)
.Build();
constexpr absl::string_view kRls = "rls_experimental";
const char kGrpc[] = "grpc";
@ -754,9 +757,9 @@ class RlsLb final : public LoadBalancingPolicy {
// Updates the picker in the work serializer.
void UpdatePickerLocked() ABSL_LOCKS_EXCLUDED(&mu_);
void MaybeExportPickCount(
GlobalInstrumentsRegistry::GlobalUInt64CounterHandle handle,
absl::string_view target, const PickResult& pick_result);
template <typename HandleType>
void MaybeExportPickCount(HandleType handle, absl::string_view target,
const PickResult& pick_result);
const std::string instance_uuid_;
@ -1961,7 +1964,7 @@ RlsLb::RlsLb(Args args)
MutexLock lock(&mu_);
cache_.ReportMetricsLocked(reporter);
},
{kMetricCacheSize, kMetricCacheEntries})) {
Duration::Seconds(5), kMetricCacheSize, kMetricCacheEntries)) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) {
gpr_log(GPR_INFO, "[rlslb %p] policy created", this);
}
@ -2230,9 +2233,9 @@ void RlsLb::UpdatePickerLocked() {
MakeRefCounted<Picker>(RefAsSubclass<RlsLb>(DEBUG_LOCATION, "Picker")));
}
void RlsLb::MaybeExportPickCount(
GlobalInstrumentsRegistry::GlobalUInt64CounterHandle handle,
absl::string_view target, const PickResult& pick_result) {
template <typename HandleType>
void RlsLb::MaybeExportPickCount(HandleType handle, absl::string_view target,
const PickResult& pick_result) {
absl::string_view pick_result_string = Match(
pick_result.result,
[](const LoadBalancingPolicy::PickResult::Complete&) {

@ -85,12 +85,16 @@ constexpr absl::string_view kWeightedRoundRobin = "weighted_round_robin";
constexpr absl::string_view kMetricLabelLocality = "grpc.lb.locality";
const auto kMetricRrFallback = GlobalInstrumentsRegistry::RegisterUInt64Counter(
"grpc.lb.wrr.rr_fallback",
"EXPERIMENTAL. Number of scheduler updates in which there were not "
"enough endpoints with valid weight, which caused the WRR policy to "
"fall back to RR behavior.",
"{update}", {kMetricLabelTarget}, {kMetricLabelLocality}, false);
const auto kMetricRrFallback =
GlobalInstrumentsRegistry::RegisterUInt64Counter(
"grpc.lb.wrr.rr_fallback",
"EXPERIMENTAL. Number of scheduler updates in which there were not "
"enough endpoints with valid weight, which caused the WRR policy to "
"fall back to RR behavior.",
"{update}", false)
.Labels(kMetricLabelTarget)
.OptionalLabels(kMetricLabelLocality)
.Build();
const auto kMetricEndpointWeightNotYetUsable =
GlobalInstrumentsRegistry::RegisterUInt64Counter(
@ -99,14 +103,20 @@ const auto kMetricEndpointWeightNotYetUsable =
"don't yet have usable weight information (i.e., either the load "
"report has not yet been received, or it is within the blackout "
"period).",
"{endpoint}", {kMetricLabelTarget}, {kMetricLabelLocality}, false);
"{endpoint}", false)
.Labels(kMetricLabelTarget)
.OptionalLabels(kMetricLabelLocality)
.Build();
const auto kMetricEndpointWeightStale =
GlobalInstrumentsRegistry::RegisterUInt64Counter(
"grpc.lb.wrr.endpoint_weight_stale",
"EXPERIMENTAL. Number of endpoints from each scheduler update whose "
"latest weight is older than the expiration period.",
"{endpoint}", {kMetricLabelTarget}, {kMetricLabelLocality}, false);
"{endpoint}", false)
.Labels(kMetricLabelTarget)
.OptionalLabels(kMetricLabelLocality)
.Build();
const auto kMetricEndpointWeights =
GlobalInstrumentsRegistry::RegisterDoubleHistogram(
@ -115,7 +125,10 @@ const auto kMetricEndpointWeights =
"Each bucket will be a counter that is incremented once for every "
"endpoint whose weight is within that range. Note that endpoints "
"without usable weights will have weight 0.",
"{weight}", {kMetricLabelTarget}, {kMetricLabelLocality}, false);
"{weight}", false)
.Labels(kMetricLabelTarget)
.OptionalLabels(kMetricLabelLocality)
.Build();
// Config for WRR policy.
class WeightedRoundRobinConfig final : public LoadBalancingPolicy::Config {

@ -32,6 +32,7 @@
#include "absl/base/thread_annotations.h"
#include "absl/functional/function_ref.h"
#include "absl/log/check.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
@ -530,7 +531,7 @@ XdsOverrideHostLb::Picker::PickOverridenHost(
// a connection attempt and queue the pick until that attempt completes.
if (idle_subchannel != nullptr) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_override_host_trace)) {
gpr_log(GPR_INFO, "Picker override found IDLE subchannel");
LOG(INFO) << "Picker override found IDLE subchannel";
}
// Deletes itself after the connection is requested.
new SubchannelConnectionRequester(std::move(idle_subchannel));
@ -540,7 +541,7 @@ XdsOverrideHostLb::Picker::PickOverridenHost(
// queue the pick and wait for the connection attempt to complete.
if (found_connecting) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_override_host_trace)) {
gpr_log(GPR_INFO, "Picker override found CONNECTING subchannel");
LOG(INFO) << "Picker override found CONNECTING subchannel";
}
return PickResult::Queue();
}
@ -549,7 +550,7 @@ XdsOverrideHostLb::Picker::PickOverridenHost(
// creation of a subchannel for that entry.
if (!address_with_no_subchannel.empty()) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_override_host_trace)) {
gpr_log(GPR_INFO, "Picker override found entry with no subchannel");
LOG(INFO) << "Picker override found entry with no subchannel";
}
if (!IsWorkSerializerDispatchEnabled()) {
new SubchannelCreationRequester(policy_, address_with_no_subchannel);

@ -79,10 +79,11 @@ namespace {
void RegisterBuiltins(CoreConfiguration::Builder* builder) {
RegisterServerCallTracerFilter(builder);
builder->channel_init()
->RegisterFilter<LameClientFilter>(GRPC_CLIENT_LAME_CHANNEL)
->RegisterV2Filter<LameClientFilter>(GRPC_CLIENT_LAME_CHANNEL)
.Terminal();
builder->channel_init()
->RegisterFilter(GRPC_SERVER_CHANNEL, &Server::kServerTopFilter)
.SkipV3()
.BeforeAll();
}

@ -57,6 +57,7 @@
#include "src/core/lib/gprpp/crash.h"
#include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/gprpp/mpscq.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/gprpp/status_helper.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/iomgr/pollset_set.h"
@ -81,6 +82,7 @@
#include "src/core/lib/surface/wait_for_cq_end_op.h"
#include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/error_utils.h"
#include "src/core/lib/transport/interception_chain.h"
namespace grpc_core {
@ -235,7 +237,8 @@ struct Server::RequestedCall {
template <typename OptionalPayload>
void Complete(OptionalPayload payload, ClientMetadata& md) {
Timestamp deadline = GetContext<Call>()->deadline();
Timestamp deadline =
md.get(GrpcTimeoutMetadata()).value_or(Timestamp::InfFuture());
switch (type) {
case RequestedCall::Type::BATCH_CALL:
CHECK(!payload.has_value());
@ -288,23 +291,29 @@ struct Server::RequestedCall {
// application to explicitly request RPCs and then matching those to incoming
// RPCs, along with a slow path by which incoming RPCs are put on a locked
// pending list if they aren't able to be matched to an application request.
class Server::RealRequestMatcherFilterStack : public RequestMatcherInterface {
class Server::RealRequestMatcher : public RequestMatcherInterface {
public:
explicit RealRequestMatcherFilterStack(Server* server)
explicit RealRequestMatcher(Server* server)
: server_(server), requests_per_cq_(server->cqs_.size()) {}
~RealRequestMatcherFilterStack() override {
~RealRequestMatcher() override {
for (LockedMultiProducerSingleConsumerQueue& queue : requests_per_cq_) {
CHECK_EQ(queue.Pop(), nullptr);
}
CHECK(pending_.empty());
CHECK(pending_filter_stack_.empty());
CHECK(pending_promises_.empty());
}
void ZombifyPending() override {
while (!pending_.empty()) {
pending_.front().calld->SetState(CallData::CallState::ZOMBIED);
pending_.front().calld->KillZombie();
pending_.pop();
while (!pending_filter_stack_.empty()) {
pending_filter_stack_.front().calld->SetState(
CallData::CallState::ZOMBIED);
pending_filter_stack_.front().calld->KillZombie();
pending_filter_stack_.pop();
}
while (!pending_promises_.empty()) {
pending_promises_.front()->Finish(absl::InternalError("Server closed"));
pending_promises_.pop();
}
}
@ -329,35 +338,56 @@ class Server::RealRequestMatcherFilterStack : public RequestMatcherInterface {
// matching calls
struct NextPendingCall {
RequestedCall* rc = nullptr;
CallData* pending;
CallData* pending_filter_stack = nullptr;
PendingCallPromises pending_promise;
};
while (true) {
NextPendingCall pending_call;
{
MutexLock lock(&server_->mu_call_);
while (!pending_.empty() &&
pending_.front().Age() > server_->max_time_in_pending_queue_) {
pending_.front().calld->SetState(CallData::CallState::ZOMBIED);
pending_.front().calld->KillZombie();
pending_.pop();
while (!pending_filter_stack_.empty() &&
pending_filter_stack_.front().Age() >
server_->max_time_in_pending_queue_) {
pending_filter_stack_.front().calld->SetState(
CallData::CallState::ZOMBIED);
pending_filter_stack_.front().calld->KillZombie();
pending_filter_stack_.pop();
}
if (!pending_.empty()) {
if (!pending_promises_.empty()) {
pending_call.rc = reinterpret_cast<RequestedCall*>(
requests_per_cq_[request_queue_index].Pop());
if (pending_call.rc != nullptr) {
pending_call.pending = pending_.front().calld;
pending_.pop();
pending_call.pending_promise =
std::move(pending_promises_.front());
pending_promises_.pop();
}
} else if (!pending_filter_stack_.empty()) {
pending_call.rc = reinterpret_cast<RequestedCall*>(
requests_per_cq_[request_queue_index].Pop());
if (pending_call.rc != nullptr) {
pending_call.pending_filter_stack =
pending_filter_stack_.front().calld;
pending_filter_stack_.pop();
}
}
}
if (pending_call.rc == nullptr) break;
if (!pending_call.pending->MaybeActivate()) {
// Zombied Call
pending_call.pending->KillZombie();
requests_per_cq_[request_queue_index].Push(
&pending_call.rc->mpscq_node);
if (pending_call.pending_filter_stack != nullptr) {
if (!pending_call.pending_filter_stack->MaybeActivate()) {
// Zombied Call
pending_call.pending_filter_stack->KillZombie();
requests_per_cq_[request_queue_index].Push(
&pending_call.rc->mpscq_node);
} else {
pending_call.pending_filter_stack->Publish(request_queue_index,
pending_call.rc);
}
} else {
pending_call.pending->Publish(request_queue_index, pending_call.rc);
if (!pending_call.pending_promise->Finish(
server(), request_queue_index, pending_call.rc)) {
requests_per_cq_[request_queue_index].Push(
&pending_call.rc->mpscq_node);
}
}
}
}
@ -395,7 +425,7 @@ class Server::RealRequestMatcherFilterStack : public RequestMatcherInterface {
}
if (rc == nullptr) {
calld->SetState(CallData::CallState::PENDING);
pending_.push(PendingCall{calld});
pending_filter_stack_.push(PendingCallFilterStack{calld});
return;
}
}
@ -403,91 +433,6 @@ class Server::RealRequestMatcherFilterStack : public RequestMatcherInterface {
calld->Publish(cq_idx, rc);
}
ArenaPromise<absl::StatusOr<MatchResult>> MatchRequest(size_t) override {
Crash("not implemented for filter stack request matcher");
}
Server* server() const final { return server_; }
private:
Server* const server_;
struct PendingCall {
CallData* calld;
Timestamp created = Timestamp::Now();
Duration Age() { return Timestamp::Now() - created; }
};
std::queue<PendingCall> pending_;
std::vector<LockedMultiProducerSingleConsumerQueue> requests_per_cq_;
};
class Server::RealRequestMatcherPromises : public RequestMatcherInterface {
public:
explicit RealRequestMatcherPromises(Server* server)
: server_(server), requests_per_cq_(server->cqs_.size()) {}
~RealRequestMatcherPromises() override {
for (LockedMultiProducerSingleConsumerQueue& queue : requests_per_cq_) {
CHECK_EQ(queue.Pop(), nullptr);
}
}
void ZombifyPending() override {
while (!pending_.empty()) {
pending_.front()->Finish(absl::InternalError("Server closed"));
pending_.pop();
}
}
void KillRequests(grpc_error_handle error) override {
for (size_t i = 0; i < requests_per_cq_.size(); i++) {
RequestedCall* rc;
while ((rc = reinterpret_cast<RequestedCall*>(
requests_per_cq_[i].Pop())) != nullptr) {
server_->FailCall(i, rc, error);
}
}
}
size_t request_queue_count() const override {
return requests_per_cq_.size();
}
void RequestCallWithPossiblePublish(size_t request_queue_index,
RequestedCall* call) override {
if (requests_per_cq_[request_queue_index].Push(&call->mpscq_node)) {
// this was the first queued request: we need to lock and start
// matching calls
struct NextPendingCall {
RequestedCall* rc = nullptr;
PendingCall pending;
};
while (true) {
NextPendingCall pending_call;
{
MutexLock lock(&server_->mu_call_);
if (!pending_.empty()) {
pending_call.rc = reinterpret_cast<RequestedCall*>(
requests_per_cq_[request_queue_index].Pop());
if (pending_call.rc != nullptr) {
pending_call.pending = std::move(pending_.front());
pending_.pop();
}
}
}
if (pending_call.rc == nullptr) break;
if (!pending_call.pending->Finish(server(), request_queue_index,
pending_call.rc)) {
requests_per_cq_[request_queue_index].Push(
&pending_call.rc->mpscq_node);
}
}
}
}
void MatchOrQueue(size_t, CallData*) override {
Crash("not implemented for promises");
}
ArenaPromise<absl::StatusOr<MatchResult>> MatchRequest(
size_t start_request_queue_index) override {
for (size_t i = 0; i < requests_per_cq_.size(); i++) {
@ -509,10 +454,11 @@ class Server::RealRequestMatcherPromises : public RequestMatcherInterface {
{
std::vector<std::shared_ptr<ActivityWaiter>> removed_pending;
MutexLock lock(&server_->mu_call_);
while (!pending_.empty() &&
pending_.front()->Age() > server_->max_time_in_pending_queue_) {
removed_pending.push_back(std::move(pending_.front()));
pending_.pop();
while (!pending_promises_.empty() &&
pending_promises_.front()->Age() >
server_->max_time_in_pending_queue_) {
removed_pending.push_back(std::move(pending_promises_.front()));
pending_promises_.pop();
}
for (loop_count = 0; loop_count < requests_per_cq_.size(); loop_count++) {
cq_idx =
@ -521,14 +467,14 @@ class Server::RealRequestMatcherPromises : public RequestMatcherInterface {
if (rc != nullptr) break;
}
if (rc == nullptr) {
if (server_->pending_backlog_protector_.Reject(pending_.size(),
if (server_->pending_backlog_protector_.Reject(pending_promises_.size(),
server_->bitgen_)) {
return Immediate(absl::ResourceExhaustedError(
"Too many pending requests for this server"));
}
auto w = std::make_shared<ActivityWaiter>(
GetContext<Activity>()->MakeOwningWaker());
pending_.push(w);
pending_promises_.push(w);
return OnCancel(
[w]() -> Poll<absl::StatusOr<MatchResult>> {
std::unique_ptr<absl::StatusOr<MatchResult>> r(
@ -546,6 +492,11 @@ class Server::RealRequestMatcherPromises : public RequestMatcherInterface {
private:
Server* const server_;
struct PendingCallFilterStack {
CallData* calld;
Timestamp created = Timestamp::Now();
Duration Age() { return Timestamp::Now() - created; }
};
struct ActivityWaiter {
using ResultType = absl::StatusOr<MatchResult>;
explicit ActivityWaiter(Waker waker) : waker(std::move(waker)) {}
@ -580,8 +531,9 @@ class Server::RealRequestMatcherPromises : public RequestMatcherInterface {
std::atomic<ResultType*> result{nullptr};
const Timestamp created = Timestamp::Now();
};
using PendingCall = std::shared_ptr<ActivityWaiter>;
std::queue<PendingCall> pending_;
using PendingCallPromises = std::shared_ptr<ActivityWaiter>;
std::queue<PendingCallFilterStack> pending_filter_stack_;
std::queue<PendingCallPromises> pending_promises_;
std::vector<LockedMultiProducerSingleConsumerQueue> requests_per_cq_;
};
@ -784,13 +736,40 @@ class ChannelBroadcaster {
} // namespace
//
// Server::TransportConnectivityWatcher
//
class Server::TransportConnectivityWatcher
: public AsyncConnectivityStateWatcherInterface {
public:
TransportConnectivityWatcher(RefCountedPtr<ServerTransport> transport,
RefCountedPtr<Server> server)
: transport_(std::move(transport)), server_(std::move(server)) {}
private:
void OnConnectivityStateChange(grpc_connectivity_state new_state,
const absl::Status& /*status*/) override {
// Don't do anything until we are being shut down.
if (new_state != GRPC_CHANNEL_SHUTDOWN) return;
// Shut down channel.
MutexLock lock(&server_->mu_global_);
server_->connections_.erase(transport_.get());
--server_->connections_open_;
server_->MaybeFinishShutdown();
}
RefCountedPtr<ServerTransport> transport_;
RefCountedPtr<Server> server_;
};
//
// Server
//
const grpc_channel_filter Server::kServerTopFilter = {
Server::CallData::StartTransportStreamOpBatch,
Server::ChannelData::MakeCallPromise,
nullptr,
[](grpc_channel_element*, CallSpineInterface*) {
// TODO(ctiller): remove the server filter when call-v3 is finalized
},
@ -826,12 +805,91 @@ RefCountedPtr<channelz::ServerNode> CreateChannelzNode(
return channelz_node;
}
absl::StatusOr<ClientMetadataHandle> CheckClientMetadata(
ValueOrFailure<ClientMetadataHandle> md) {
if (!md.ok()) {
return absl::InternalError("Missing metadata");
}
if (!md.value()->get_pointer(HttpPathMetadata())) {
return absl::InternalError("Missing :path header");
}
if (!md.value()->get_pointer(HttpAuthorityMetadata())) {
return absl::InternalError("Missing :authority header");
}
return std::move(*md);
}
} // namespace
auto Server::MatchAndPublishCall(CallHandler call_handler) {
call_handler.SpawnGuarded("request_matcher", [this, call_handler]() mutable {
return TrySeq(
// Wait for initial metadata to pass through all filters
Map(call_handler.PullClientInitialMetadata(), CheckClientMetadata),
// Match request with requested call
[this, call_handler](ClientMetadataHandle md) mutable {
auto* registered_method = static_cast<RegisteredMethod*>(
md->get(GrpcRegisteredMethod()).value_or(nullptr));
RequestMatcherInterface* rm;
grpc_server_register_method_payload_handling payload_handling =
GRPC_SRM_PAYLOAD_NONE;
if (registered_method == nullptr) {
rm = unregistered_request_matcher_.get();
} else {
payload_handling = registered_method->payload_handling;
rm = registered_method->matcher.get();
}
auto maybe_read_first_message = If(
payload_handling == GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER,
[call_handler]() mutable { return call_handler.PullMessage(); },
[]() -> ValueOrFailure<absl::optional<MessageHandle>> {
return ValueOrFailure<absl::optional<MessageHandle>>(
absl::nullopt);
});
return TryJoin<absl::StatusOr>(
std::move(maybe_read_first_message), rm->MatchRequest(0),
[md = std::move(md)]() mutable {
return ValueOrFailure<ClientMetadataHandle>(std::move(md));
});
},
// Publish call to cq
[call_handler, this](std::tuple<absl::optional<MessageHandle>,
RequestMatcherInterface::MatchResult,
ClientMetadataHandle>
r) {
RequestMatcherInterface::MatchResult& mr = std::get<1>(r);
auto md = std::move(std::get<2>(r));
auto* rc = mr.TakeCall();
rc->Complete(std::move(std::get<0>(r)), *md);
grpc_call* call =
MakeServerCall(call_handler, std::move(md), this,
rc->cq_bound_to_call, rc->initial_metadata);
*rc->call = call;
return Map(WaitForCqEndOp(false, rc->tag, absl::OkStatus(), mr.cq()),
[rc = std::unique_ptr<RequestedCall>(rc)](Empty) {
return absl::OkStatus();
});
});
});
}
absl::StatusOr<RefCountedPtr<UnstartedCallDestination>>
Server::MakeCallDestination(const ChannelArgs& args) {
InterceptionChainBuilder builder(args);
builder.AddOnClientInitialMetadata(
[this](ClientMetadata& md) { SetRegisteredMethodOnMetadata(md); });
CoreConfiguration::Get().channel_init().AddToInterceptionChainBuilder(
GRPC_SERVER_CHANNEL, builder);
return builder.Build(
MakeCallDestinationFromHandlerFunction([this](CallHandler handler) {
return MatchAndPublishCall(std::move(handler));
}));
}
Server::Server(const ChannelArgs& args)
: channel_args_(args),
channelz_node_(CreateChannelzNode(args)),
server_call_tracer_factory_(ServerCallTracerFactory::Get(args)),
compression_options_(CompressionOptionsFromChannelArgs(args)),
max_time_in_pending_queue_(Duration::Seconds(
channel_args_
.GetInt(GRPC_ARG_SERVER_MAX_UNREQUESTED_TIME_IN_SERVER_SECONDS)
@ -862,15 +920,6 @@ void Server::AddListener(OrphanablePtr<ListenerInterface> listener) {
}
void Server::Start() {
auto make_real_request_matcher =
[this]() -> std::unique_ptr<RequestMatcherInterface> {
if (IsPromiseBasedServerCallEnabled()) {
return std::make_unique<RealRequestMatcherPromises>(this);
} else {
return std::make_unique<RealRequestMatcherFilterStack>(this);
}
};
started_ = true;
for (grpc_completion_queue* cq : cqs_) {
if (grpc_cq_can_listen(cq)) {
@ -878,11 +927,11 @@ void Server::Start() {
}
}
if (unregistered_request_matcher_ == nullptr) {
unregistered_request_matcher_ = make_real_request_matcher();
unregistered_request_matcher_ = std::make_unique<RealRequestMatcher>(this);
}
for (auto& rm : registered_methods_) {
if (rm.second->matcher == nullptr) {
rm.second->matcher = make_real_request_matcher();
rm.second->matcher = std::make_unique<RealRequestMatcher>(this);
}
}
{
@ -913,37 +962,61 @@ grpc_error_handle Server::SetupTransport(
const RefCountedPtr<channelz::SocketNode>& socket_node) {
// Create channel.
global_stats().IncrementServerChannelsCreated();
absl::StatusOr<OrphanablePtr<Channel>> channel =
LegacyChannel::Create("", args.SetObject(transport), GRPC_SERVER_CHANNEL);
if (!channel.ok()) {
return absl_status_to_grpc_error(channel.status());
}
ChannelData* chand = static_cast<ChannelData*>(
grpc_channel_stack_element((*channel)->channel_stack(), 0)->channel_data);
// Set up CQs.
size_t cq_idx;
for (cq_idx = 0; cq_idx < cqs_.size(); cq_idx++) {
if (grpc_cq_pollset(cqs_[cq_idx]) == accepting_pollset) break;
}
if (cq_idx == cqs_.size()) {
// Completion queue not found. Pick a random one to publish new calls to.
cq_idx = static_cast<size_t>(rand()) % std::max<size_t>(1, cqs_.size());
}
// Set up channelz node.
intptr_t channelz_socket_uuid = 0;
if (socket_node != nullptr) {
channelz_socket_uuid = socket_node->uuid();
channelz_node_->AddChildSocket(socket_node);
}
// Initialize chand.
chand->InitTransport(Ref(), std::move(*channel), cq_idx, transport,
channelz_socket_uuid);
if (transport->server_transport() != nullptr) {
// Take ownership
// TODO(ctiller): post-v3-transition make this method take an
// OrphanablePtr<ServerTransport> directly.
OrphanablePtr<ServerTransport> t(transport->server_transport());
auto destination = MakeCallDestination(args.SetObject(transport));
if (!destination.ok()) {
return absl_status_to_grpc_error(destination.status());
}
// TODO(ctiller): add channelz node
t->SetCallDestination(std::move(*destination));
MutexLock lock(&mu_global_);
if (ShutdownCalled()) {
t->DisconnectWithError(GRPC_ERROR_CREATE("Server shutdown"));
}
t->StartConnectivityWatch(MakeOrphanable<TransportConnectivityWatcher>(
t->RefAsSubclass<ServerTransport>(), Ref()));
gpr_log(GPR_INFO, "Adding connection");
connections_.emplace(std::move(t));
++connections_open_;
} else {
CHECK(transport->filter_stack_transport() != nullptr);
absl::StatusOr<OrphanablePtr<Channel>> channel = LegacyChannel::Create(
"", args.SetObject(transport), GRPC_SERVER_CHANNEL);
if (!channel.ok()) {
return absl_status_to_grpc_error(channel.status());
}
ChannelData* chand = static_cast<ChannelData*>(
grpc_channel_stack_element((*channel)->channel_stack(), 0)
->channel_data);
// Set up CQs.
size_t cq_idx;
for (cq_idx = 0; cq_idx < cqs_.size(); cq_idx++) {
if (grpc_cq_pollset(cqs_[cq_idx]) == accepting_pollset) break;
}
if (cq_idx == cqs_.size()) {
// Completion queue not found. Pick a random one to publish new calls to.
cq_idx = static_cast<size_t>(rand()) % std::max<size_t>(1, cqs_.size());
}
intptr_t channelz_socket_uuid = 0;
if (socket_node != nullptr) {
channelz_socket_uuid = socket_node->uuid();
channelz_node_->AddChildSocket(socket_node);
}
// Initialize chand.
chand->InitTransport(Ref(), std::move(*channel), cq_idx, transport,
channelz_socket_uuid);
}
return absl::OkStatus();
}
bool Server::HasOpenConnections() {
MutexLock lock(&mu_global_);
return !channels_.empty();
return !channels_.empty() || !connections_.empty();
}
void Server::SetRegisteredMethodAllocator(
@ -1023,16 +1096,18 @@ void Server::MaybeFinishShutdown() {
MutexLock lock(&mu_call_);
KillPendingWorkLocked(GRPC_ERROR_CREATE("Server Shutdown"));
}
if (!channels_.empty() || listeners_destroyed_ < listeners_.size()) {
if (!channels_.empty() || connections_open_ > 0 ||
listeners_destroyed_ < listeners_.size()) {
if (gpr_time_cmp(gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME),
last_shutdown_message_time_),
gpr_time_from_seconds(1, GPR_TIMESPAN)) >= 0) {
last_shutdown_message_time_ = gpr_now(GPR_CLOCK_REALTIME);
gpr_log(GPR_DEBUG,
"Waiting for %" PRIuPTR " channels and %" PRIuPTR "/%" PRIuPTR
"Waiting for %" PRIuPTR " channels %" PRIuPTR
" connections and %" PRIuPTR "/%" PRIuPTR
" listeners to be destroyed before shutting down server",
channels_.size(), listeners_.size() - listeners_destroyed_,
listeners_.size());
channels_.size(), connections_open_,
listeners_.size() - listeners_destroyed_, listeners_.size());
}
return;
}
@ -1095,6 +1170,7 @@ void DonePublishedShutdown(void* /*done_arg*/, grpc_cq_completion* storage) {
// -- Once there are no more calls in progress, the channel is closed.
void Server::ShutdownAndNotify(grpc_completion_queue* cq, void* tag) {
ChannelBroadcaster broadcaster;
absl::flat_hash_set<OrphanablePtr<ServerTransport>> removing_connections;
{
// Wait for startup to be finished. Locks mu_global.
MutexLock lock(&mu_global_);
@ -1114,6 +1190,7 @@ void Server::ShutdownAndNotify(grpc_completion_queue* cq, void* tag) {
}
last_shutdown_message_time_ = gpr_now(GPR_CLOCK_REALTIME);
broadcaster.FillChannelsLocked(GetChannelsLocked());
removing_connections.swap(connections_);
// Collect all unregistered then registered calls.
{
MutexLock lock(&mu_call_);
@ -1300,17 +1377,6 @@ Server::ChannelData::~ChannelData() {
}
}
Arena* Server::ChannelData::CreateArena() { return channel_->CreateArena(); }
absl::StatusOr<CallInitiator> Server::ChannelData::CreateCall(
ClientMetadataHandle client_initial_metadata, Arena* arena) {
SetRegisteredMethodOnMetadata(*client_initial_metadata);
auto call = MakeServerCall(std::move(client_initial_metadata), server_.get(),
channel_.get(), arena);
InitCall(call);
return CallInitiator(std::move(call));
}
void Server::ChannelData::InitTransport(RefCountedPtr<Server> server,
OrphanablePtr<Channel> channel,
size_t cq_idx, Transport* transport,
@ -1327,22 +1393,15 @@ void Server::ChannelData::InitTransport(RefCountedPtr<Server> server,
}
// Start accept_stream transport op.
grpc_transport_op* op = grpc_make_transport_op(nullptr);
int accept_stream_types = 0;
if (transport->filter_stack_transport() != nullptr) {
++accept_stream_types;
op->set_accept_stream = true;
op->set_accept_stream_fn = AcceptStream;
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) {
++accept_stream_types;
transport->server_transport()->SetAcceptor(this);
}
CHECK_EQ(accept_stream_types, 1);
CHECK(transport->filter_stack_transport() != nullptr);
op->set_accept_stream = true;
op->set_accept_stream_fn = AcceptStream;
op->set_registered_method_matcher_fn = [](void* arg,
ClientMetadata* metadata) {
static_cast<ChannelData*>(arg)->server_->SetRegisteredMethodOnMetadata(
*metadata);
};
op->set_accept_stream_user_data = this;
op->start_connectivity_watch = MakeOrphanable<ConnectivityWatcher>(this);
if (server_->ShutdownCalled()) {
op->disconnect_with_error = GRPC_ERROR_CREATE("Server shutdown");
@ -1350,24 +1409,23 @@ void Server::ChannelData::InitTransport(RefCountedPtr<Server> server,
transport->PerformOp(op);
}
Server::RegisteredMethod* Server::ChannelData::GetRegisteredMethod(
Server::RegisteredMethod* Server::GetRegisteredMethod(
const absl::string_view& host, const absl::string_view& path) {
if (server_->registered_methods_.empty()) return nullptr;
if (registered_methods_.empty()) return nullptr;
// check for an exact match with host
auto it = server_->registered_methods_.find(std::make_pair(host, path));
if (it != server_->registered_methods_.end()) {
auto it = registered_methods_.find(std::make_pair(host, path));
if (it != registered_methods_.end()) {
return it->second.get();
}
// check for wildcard method definition (no host set)
it = server_->registered_methods_.find(std::make_pair("", path));
if (it != server_->registered_methods_.end()) {
it = registered_methods_.find(std::make_pair("", path));
if (it != registered_methods_.end()) {
return it->second.get();
}
return nullptr;
}
void Server::ChannelData::SetRegisteredMethodOnMetadata(
ClientMetadata& metadata) {
void Server::SetRegisteredMethodOnMetadata(ClientMetadata& metadata) {
auto* authority = metadata.get_pointer(HttpAuthorityMetadata());
if (authority == nullptr) {
authority = metadata.get_pointer(HostMetadata());
@ -1403,188 +1461,14 @@ void Server::ChannelData::AcceptStream(void* arg, Transport* /*transport*/,
grpc_call* call;
grpc_error_handle error = grpc_call_create(&args, &call);
grpc_call_stack* call_stack = grpc_call_get_call_stack(call);
if (call_stack == nullptr) { // Promise based calls do not have a call stack
CHECK(error.ok());
CHECK(IsPromiseBasedServerCallEnabled());
CHECK_NE(call_stack, nullptr);
grpc_call_element* elem = grpc_call_stack_element(call_stack, 0);
auto* calld = static_cast<Server::CallData*>(elem->call_data);
if (!error.ok()) {
calld->FailCallCreation();
return;
} else {
grpc_call_element* elem = grpc_call_stack_element(call_stack, 0);
auto* calld = static_cast<Server::CallData*>(elem->call_data);
if (!error.ok()) {
calld->FailCallCreation();
return;
}
calld->Start(elem);
}
}
namespace {
auto CancelledDueToServerShutdown() {
return [] {
return ServerMetadataFromStatus(absl::CancelledError("Server shutdown"));
};
}
} // namespace
void Server::ChannelData::InitCall(RefCountedPtr<CallSpineInterface> call) {
call->SpawnGuarded("request_matcher", [this, call]() {
return TrySeq(
// Wait for initial metadata to pass through all filters
Map(call->PullClientInitialMetadata(),
[](ValueOrFailure<ClientMetadataHandle> md)
-> absl::StatusOr<ClientMetadataHandle> {
if (!md.ok()) {
return absl::InternalError("Missing metadata");
}
if (!md.value()->get_pointer(HttpPathMetadata())) {
return absl::InternalError("Missing :path header");
}
if (!md.value()->get_pointer(HttpAuthorityMetadata())) {
return absl::InternalError("Missing :authority header");
}
return std::move(*md);
}),
// Match request with requested call
[this, call](ClientMetadataHandle md) {
auto* registered_method = static_cast<RegisteredMethod*>(
md->get(GrpcRegisteredMethod()).value_or(nullptr));
RequestMatcherInterface* rm;
grpc_server_register_method_payload_handling payload_handling =
GRPC_SRM_PAYLOAD_NONE;
if (registered_method == nullptr) {
rm = server_->unregistered_request_matcher_.get();
} else {
payload_handling = registered_method->payload_handling;
rm = registered_method->matcher.get();
}
auto maybe_read_first_message = If(
payload_handling == GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER,
[call]() { return call->PullClientToServerMessage(); },
[]() -> ValueOrFailure<absl::optional<MessageHandle>> {
return ValueOrFailure<absl::optional<MessageHandle>>(
absl::nullopt);
});
return TryJoin<absl::StatusOr>(
std::move(maybe_read_first_message), rm->MatchRequest(cq_idx()),
[md = std::move(md)]() mutable {
return ValueOrFailure<ClientMetadataHandle>(std::move(md));
});
},
// Publish call to cq
[](std::tuple<absl::optional<MessageHandle>,
RequestMatcherInterface::MatchResult,
ClientMetadataHandle>
r) {
RequestMatcherInterface::MatchResult& mr = std::get<1>(r);
auto md = std::move(std::get<2>(r));
auto* rc = mr.TakeCall();
rc->Complete(std::move(std::get<0>(r)), *md);
auto* call_context = GetContext<CallContext>();
const auto* deadline = md->get_pointer(GrpcTimeoutMetadata());
if (deadline != nullptr) {
GetContext<Call>()->UpdateDeadline(*deadline);
}
*rc->call = call_context->c_call();
grpc_call_ref(*rc->call);
grpc_call_set_completion_queue(call_context->c_call(),
rc->cq_bound_to_call);
call_context->server_call_context()->PublishInitialMetadata(
std::move(md), rc->initial_metadata);
// TODO(ctiller): publish metadata
return Map(WaitForCqEndOp(false, rc->tag, absl::OkStatus(), mr.cq()),
[rc = std::unique_ptr<RequestedCall>(rc)](Empty) {
return absl::OkStatus();
});
});
});
}
ArenaPromise<ServerMetadataHandle> Server::ChannelData::MakeCallPromise(
grpc_channel_element* elem, CallArgs call_args, NextPromiseFactory) {
auto* chand = static_cast<Server::ChannelData*>(elem->channel_data);
auto* server = chand->server_.get();
if (server->ShutdownCalled()) return CancelledDueToServerShutdown();
auto cleanup_ref =
absl::MakeCleanup([server] { server->ShutdownUnrefOnRequest(); });
if (!server->ShutdownRefOnRequest()) return CancelledDueToServerShutdown();
auto path_ptr =
call_args.client_initial_metadata->get_pointer(HttpPathMetadata());
if (path_ptr == nullptr) {
return [] {
return ServerMetadataFromStatus(
absl::InternalError("Missing :path header"));
};
}
auto host_ptr =
call_args.client_initial_metadata->get_pointer(HttpAuthorityMetadata());
if (host_ptr == nullptr) {
return [] {
return ServerMetadataFromStatus(
absl::InternalError("Missing :authority header"));
};
}
// Find request matcher.
RequestMatcherInterface* matcher;
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) {
matcher = rm->matcher.get();
switch (rm->payload_handling) {
case GRPC_SRM_PAYLOAD_NONE:
break;
case GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER:
maybe_read_first_message =
Map(call_args.client_to_server_messages->Next(),
[](NextResult<MessageHandle> msg)
-> absl::StatusOr<NextResult<MessageHandle>> {
return std::move(msg);
});
}
} else {
matcher = server->unregistered_request_matcher_.get();
}
return TrySeq(
std::move(maybe_read_first_message),
[cleanup_ref = std::move(cleanup_ref), matcher,
chand](NextResult<MessageHandle> payload) mutable {
return Map(
[cleanup_ref = std::move(cleanup_ref),
mr = matcher->MatchRequest(chand->cq_idx())]() mutable {
return mr();
},
[payload = std::move(payload)](
absl::StatusOr<RequestMatcherInterface::MatchResult> mr) mutable
-> absl::StatusOr<std::pair<RequestMatcherInterface::MatchResult,
NextResult<MessageHandle>>> {
if (!mr.ok()) return mr.status();
return std::make_pair(std::move(*mr), std::move(payload));
});
},
[call_args =
std::move(call_args)](std::pair<RequestMatcherInterface::MatchResult,
NextResult<MessageHandle>>
r) mutable {
auto& mr = r.first;
auto& payload = r.second;
auto* rc = mr.TakeCall();
auto* cq_for_new_request = mr.cq();
auto* server_call_context =
GetContext<CallContext>()->server_call_context();
rc->Complete(std::move(payload), *call_args.client_initial_metadata);
server_call_context->PublishInitialMetadata(
std::move(call_args.client_initial_metadata), rc->initial_metadata);
return server_call_context->MakeTopOfServerCallPromise(
std::move(call_args), rc->cq_bound_to_call,
[rc, cq_for_new_request](grpc_call* call) {
*rc->call = call;
grpc_cq_end_op(cq_for_new_request, rc->tag, absl::OkStatus(),
Server::DoneRequestEvent, rc, &rc->completion,
true);
});
});
calld->Start(elem);
}
void Server::ChannelData::FinishDestroy(void* arg,

@ -38,7 +38,9 @@
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include <grpc/compression.h>
#include <grpc/grpc.h>
#include <grpc/passive_listener.h>
#include <grpc/slice.h>
#include <grpc/support/port_platform.h>
#include <grpc/support/time.h>
@ -74,6 +76,9 @@
"grpc.server.max_pending_requests_hard_limit"
namespace grpc_core {
namespace experimental {
class PassiveListenerImpl;
} // namespace experimental
extern TraceFlag grpc_server_channel_trace;
@ -112,7 +117,7 @@ class Server : public ServerInterface,
/// Interface for listeners.
/// Implementations must override the Orphan() method, which should stop
/// listening and initiate destruction of the listener.
class ListenerInterface : public Orphanable {
class ListenerInterface : public InternallyRefCounted<ListenerInterface> {
public:
~ListenerInterface() override = default;
@ -211,17 +216,28 @@ class Server : public ServerInterface,
void SendGoaways() ABSL_LOCKS_EXCLUDED(mu_global_, mu_call_);
grpc_compression_options compression_options() const override {
return compression_options_;
}
private:
// note: the grpc_core::Server redundant namespace qualification is
// required for older gcc versions.
// TODO(yashykt): eliminate this friend statement as part of your upcoming
// server listener refactoring.
friend absl::Status(::grpc_server_add_passive_listener)(
grpc_core::Server* server, grpc_server_credentials* credentials,
std::shared_ptr<grpc_core::experimental::PassiveListenerImpl>
passive_listener);
struct RequestedCall;
class RequestMatcherInterface;
class RealRequestMatcherFilterStack;
class RealRequestMatcherPromises;
class RealRequestMatcher;
class AllocatingRequestMatcherBase;
class AllocatingRequestMatcherBatch;
class AllocatingRequestMatcherRegistered;
class ChannelData final : public ServerTransport::Acceptor {
class ChannelData final {
public:
ChannelData() = default;
~ChannelData();
@ -234,26 +250,17 @@ class Server : public ServerInterface,
Channel* channel() const { return channel_.get(); }
size_t cq_idx() const { return cq_idx_; }
RegisteredMethod* GetRegisteredMethod(const absl::string_view& host,
const absl::string_view& path);
// Filter vtable functions.
static grpc_error_handle InitChannelElement(
grpc_channel_element* elem, grpc_channel_element_args* args);
static void DestroyChannelElement(grpc_channel_element* elem);
static ArenaPromise<ServerMetadataHandle> MakeCallPromise(
grpc_channel_element* elem, CallArgs call_args, NextPromiseFactory);
void InitCall(RefCountedPtr<CallSpineInterface> call);
Arena* CreateArena() override;
absl::StatusOr<CallInitiator> CreateCall(
ClientMetadataHandle client_initial_metadata, Arena* arena) override;
private:
class ConnectivityWatcher;
static void AcceptStream(void* arg, Transport* /*transport*/,
const void* transport_server_data);
void SetRegisteredMethodOnMetadata(ClientMetadata& metadata);
void Destroy() ABSL_EXCLUSIVE_LOCKS_REQUIRED(server_->mu_global_);
@ -384,6 +391,12 @@ class Server : public ServerInterface,
using is_transparent = void;
};
class TransportConnectivityWatcher;
RegisteredMethod* GetRegisteredMethod(const absl::string_view& host,
const absl::string_view& path);
void SetRegisteredMethodOnMetadata(ClientMetadata& metadata);
static void ListenerDestroyDone(void* arg, grpc_error_handle error);
static void DoneShutdownEvent(void* server,
@ -445,6 +458,10 @@ class Server : public ServerInterface,
return shutdown_refs_.load(std::memory_order_acquire) == 0;
}
auto MatchAndPublishCall(CallHandler call_handler);
absl::StatusOr<RefCountedPtr<UnstartedCallDestination>> MakeCallDestination(
const ChannelArgs& args);
ChannelArgs const channel_args_;
RefCountedPtr<channelz::ServerNode> channelz_node_;
std::unique_ptr<grpc_server_config_fetcher> config_fetcher_;
@ -453,6 +470,7 @@ class Server : public ServerInterface,
std::vector<grpc_completion_queue*> cqs_;
std::vector<grpc_pollset*> pollsets_;
bool started_ = false;
const grpc_compression_options compression_options_;
// The two following mutexes control access to server-state.
// mu_global_ controls access to non-call-related state (e.g., channel state).
@ -500,6 +518,9 @@ class Server : public ServerInterface,
absl::BitGen bitgen_ ABSL_GUARDED_BY(mu_call_);
std::list<ChannelData*> channels_;
absl::flat_hash_set<OrphanablePtr<ServerTransport>> connections_
ABSL_GUARDED_BY(mu_global_);
size_t connections_open_ ABSL_GUARDED_BY(mu_global_) = 0;
std::list<Listener> listeners_;
size_t listeners_destroyed_ = 0;

@ -17,6 +17,7 @@
#ifndef GRPC_SRC_CORE_SERVER_SERVER_INTERFACE_H
#define GRPC_SRC_CORE_SERVER_SERVER_INTERFACE_H
#include <grpc/impl/compression_types.h>
#include <grpc/support/port_platform.h>
#include "src/core/channelz/channelz.h"
@ -36,6 +37,7 @@ class ServerInterface {
virtual const ChannelArgs& channel_args() const = 0;
virtual channelz::ServerNode* channelz_node() const = 0;
virtual ServerCallTracerFactory* server_call_tracer_factory() const = 0;
virtual grpc_compression_options compression_options() const = 0;
};
} // namespace grpc_core

@ -23,6 +23,7 @@
#include <string.h>
#include "absl/log/check.h"
#include "absl/log/log.h"
#include "upb/mem/arena.hpp"
#include <grpc/credentials.h>
@ -87,7 +88,7 @@ typedef struct alts_tsi_handshaker_result {
static tsi_result handshaker_result_extract_peer(
const tsi_handshaker_result* self, tsi_peer* peer) {
if (self == nullptr || peer == nullptr) {
gpr_log(GPR_ERROR, "Invalid argument to handshaker_result_extract_peer()");
LOG(ERROR) << "Invalid argument to handshaker_result_extract_peer()";
return TSI_INVALID_ARGUMENT;
}
alts_tsi_handshaker_result* result =
@ -97,7 +98,7 @@ static tsi_result handshaker_result_extract_peer(
tsi_result ok = tsi_construct_peer(kTsiAltsNumOfPeerProperties, peer);
int index = 0;
if (ok != TSI_OK) {
gpr_log(GPR_ERROR, "Failed to construct tsi peer");
LOG(ERROR) << "Failed to construct tsi peer";
return ok;
}
CHECK_NE(&peer->properties[index], nullptr);
@ -106,7 +107,7 @@ static tsi_result handshaker_result_extract_peer(
&peer->properties[index]);
if (ok != TSI_OK) {
tsi_peer_destruct(peer);
gpr_log(GPR_ERROR, "Failed to set tsi peer property");
LOG(ERROR) << "Failed to set tsi peer property";
return ok;
}
index++;
@ -116,7 +117,7 @@ static tsi_result handshaker_result_extract_peer(
&peer->properties[index]);
if (ok != TSI_OK) {
tsi_peer_destruct(peer);
gpr_log(GPR_ERROR, "Failed to set tsi peer property");
LOG(ERROR) << "Failed to set tsi peer property";
}
index++;
CHECK_NE(&peer->properties[index], nullptr);
@ -126,7 +127,7 @@ static tsi_result handshaker_result_extract_peer(
GRPC_SLICE_LENGTH(result->rpc_versions), &peer->properties[index]);
if (ok != TSI_OK) {
tsi_peer_destruct(peer);
gpr_log(GPR_ERROR, "Failed to set tsi peer property");
LOG(ERROR) << "Failed to set tsi peer property";
}
index++;
CHECK_NE(&peer->properties[index], nullptr);
@ -136,7 +137,7 @@ static tsi_result handshaker_result_extract_peer(
GRPC_SLICE_LENGTH(result->serialized_context), &peer->properties[index]);
if (ok != TSI_OK) {
tsi_peer_destruct(peer);
gpr_log(GPR_ERROR, "Failed to set tsi peer property");
LOG(ERROR) << "Failed to set tsi peer property";
}
index++;
CHECK_NE(&peer->properties[index], nullptr);
@ -146,7 +147,7 @@ static tsi_result handshaker_result_extract_peer(
&peer->properties[index]);
if (ok != TSI_OK) {
tsi_peer_destruct(peer);
gpr_log(GPR_ERROR, "Failed to set tsi peer property");
LOG(ERROR) << "Failed to set tsi peer property";
}
CHECK(++index == kTsiAltsNumOfPeerProperties);
return ok;
@ -163,8 +164,7 @@ static tsi_result handshaker_result_create_zero_copy_grpc_protector(
const tsi_handshaker_result* self, size_t* max_output_protected_frame_size,
tsi_zero_copy_grpc_protector** protector) {
if (self == nullptr || protector == nullptr) {
gpr_log(GPR_ERROR,
"Invalid arguments to create_zero_copy_grpc_protector()");
LOG(ERROR) << "Invalid arguments to create_zero_copy_grpc_protector()";
return TSI_INVALID_ARGUMENT;
}
alts_tsi_handshaker_result* result =
@ -198,7 +198,7 @@ static tsi_result handshaker_result_create_zero_copy_grpc_protector(
/*is_integrity_only=*/false, /*enable_extra_copy=*/false,
max_output_protected_frame_size, protector);
if (ok != TSI_OK) {
gpr_log(GPR_ERROR, "Failed to create zero-copy grpc protector");
LOG(ERROR) << "Failed to create zero-copy grpc protector";
}
return ok;
}
@ -207,8 +207,8 @@ static tsi_result handshaker_result_create_frame_protector(
const tsi_handshaker_result* self, size_t* max_output_protected_frame_size,
tsi_frame_protector** protector) {
if (self == nullptr || protector == nullptr) {
gpr_log(GPR_ERROR,
"Invalid arguments to handshaker_result_create_frame_protector()");
LOG(ERROR)
<< "Invalid arguments to handshaker_result_create_frame_protector()";
return TSI_INVALID_ARGUMENT;
}
alts_tsi_handshaker_result* result =
@ -219,7 +219,7 @@ static tsi_result handshaker_result_create_frame_protector(
kAltsAes128GcmRekeyKeyLength, result->is_client, /*is_rekey=*/true,
max_output_protected_frame_size, protector);
if (ok != TSI_OK) {
gpr_log(GPR_ERROR, "Failed to create frame protector");
LOG(ERROR) << "Failed to create frame protector";
}
return ok;
}
@ -228,8 +228,7 @@ static tsi_result handshaker_result_get_unused_bytes(
const tsi_handshaker_result* self, const unsigned char** bytes,
size_t* bytes_size) {
if (self == nullptr || bytes == nullptr || bytes_size == nullptr) {
gpr_log(GPR_ERROR,
"Invalid arguments to handshaker_result_get_unused_bytes()");
LOG(ERROR) << "Invalid arguments to handshaker_result_get_unused_bytes()";
return TSI_INVALID_ARGUMENT;
}
alts_tsi_handshaker_result* result =
@ -267,7 +266,7 @@ tsi_result alts_tsi_handshaker_result_create(grpc_gcp_HandshakerResp* resp,
bool is_client,
tsi_handshaker_result** result) {
if (result == nullptr || resp == nullptr) {
gpr_log(GPR_ERROR, "Invalid arguments to create_handshaker_result()");
LOG(ERROR) << "Invalid arguments to create_handshaker_result()";
return TSI_INVALID_ARGUMENT;
}
const grpc_gcp_HandshakerResult* hresult =
@ -275,42 +274,42 @@ tsi_result alts_tsi_handshaker_result_create(grpc_gcp_HandshakerResp* resp,
const grpc_gcp_Identity* identity =
grpc_gcp_HandshakerResult_peer_identity(hresult);
if (identity == nullptr) {
gpr_log(GPR_ERROR, "Invalid identity");
LOG(ERROR) << "Invalid identity";
return TSI_FAILED_PRECONDITION;
}
upb_StringView peer_service_account =
grpc_gcp_Identity_service_account(identity);
if (peer_service_account.size == 0) {
gpr_log(GPR_ERROR, "Invalid peer service account");
LOG(ERROR) << "Invalid peer service account";
return TSI_FAILED_PRECONDITION;
}
upb_StringView key_data = grpc_gcp_HandshakerResult_key_data(hresult);
if (key_data.size < kAltsAes128GcmRekeyKeyLength) {
gpr_log(GPR_ERROR, "Bad key length");
LOG(ERROR) << "Bad key length";
return TSI_FAILED_PRECONDITION;
}
const grpc_gcp_RpcProtocolVersions* peer_rpc_version =
grpc_gcp_HandshakerResult_peer_rpc_versions(hresult);
if (peer_rpc_version == nullptr) {
gpr_log(GPR_ERROR, "Peer does not set RPC protocol versions.");
LOG(ERROR) << "Peer does not set RPC protocol versions.";
return TSI_FAILED_PRECONDITION;
}
upb_StringView application_protocol =
grpc_gcp_HandshakerResult_application_protocol(hresult);
if (application_protocol.size == 0) {
gpr_log(GPR_ERROR, "Invalid application protocol");
LOG(ERROR) << "Invalid application protocol";
return TSI_FAILED_PRECONDITION;
}
upb_StringView record_protocol =
grpc_gcp_HandshakerResult_record_protocol(hresult);
if (record_protocol.size == 0) {
gpr_log(GPR_ERROR, "Invalid record protocol");
LOG(ERROR) << "Invalid record protocol";
return TSI_FAILED_PRECONDITION;
}
const grpc_gcp_Identity* local_identity =
grpc_gcp_HandshakerResult_local_identity(hresult);
if (local_identity == nullptr) {
gpr_log(GPR_ERROR, "Invalid local identity");
LOG(ERROR) << "Invalid local identity";
return TSI_FAILED_PRECONDITION;
}
upb_StringView local_service_account =
@ -331,7 +330,7 @@ tsi_result alts_tsi_handshaker_result_create(grpc_gcp_HandshakerResp* resp,
bool serialized = grpc_gcp_rpc_protocol_versions_encode(
peer_rpc_version, rpc_versions_arena.ptr(), &sresult->rpc_versions);
if (!serialized) {
gpr_log(GPR_ERROR, "Failed to serialize peer's RPC protocol versions.");
LOG(ERROR) << "Failed to serialize peer's RPC protocol versions.";
return TSI_FAILED_PRECONDITION;
}
upb::Arena context_arena;
@ -348,7 +347,7 @@ tsi_result alts_tsi_handshaker_result_create(grpc_gcp_HandshakerResp* resp,
context, const_cast<grpc_gcp_RpcProtocolVersions*>(peer_rpc_version));
grpc_gcp_Identity* peer_identity = const_cast<grpc_gcp_Identity*>(identity);
if (peer_identity == nullptr) {
gpr_log(GPR_ERROR, "Null peer identity in ALTS context.");
LOG(ERROR) << "Null peer identity in ALTS context.";
return TSI_FAILED_PRECONDITION;
}
if (grpc_gcp_Identity_attributes_size(identity) != 0) {
@ -372,7 +371,7 @@ tsi_result alts_tsi_handshaker_result_create(grpc_gcp_HandshakerResp* resp,
char* serialized_ctx = grpc_gcp_AltsContext_serialize(
context, context_arena.ptr(), &serialized_ctx_length);
if (serialized_ctx == nullptr) {
gpr_log(GPR_ERROR, "Failed to serialize peer's ALTS context.");
LOG(ERROR) << "Failed to serialize peer's ALTS context.";
return TSI_FAILED_PRECONDITION;
}
sresult->serialized_context =
@ -388,7 +387,7 @@ static void on_handshaker_service_resp_recv(void* arg,
grpc_error_handle error) {
alts_handshaker_client* client = static_cast<alts_handshaker_client*>(arg);
if (client == nullptr) {
gpr_log(GPR_ERROR, "ALTS handshaker client is nullptr");
LOG(ERROR) << "ALTS handshaker client is nullptr";
return;
}
bool success = true;
@ -440,7 +439,7 @@ static tsi_result alts_tsi_handshaker_continue_handshaker_next(
handshaker->client_vtable_for_testing, handshaker->is_client,
handshaker->max_frame_size, error);
if (client == nullptr) {
gpr_log(GPR_ERROR, "Failed to create ALTS handshaker client");
LOG(ERROR) << "Failed to create ALTS handshaker client";
if (error != nullptr) *error = "Failed to create ALTS handshaker client";
return TSI_FAILED_PRECONDITION;
}
@ -449,7 +448,7 @@ static tsi_result alts_tsi_handshaker_continue_handshaker_next(
CHECK_EQ(handshaker->client, nullptr);
handshaker->client = client;
if (handshaker->shutdown) {
gpr_log(GPR_INFO, "TSI handshake shutdown");
LOG(INFO) << "TSI handshake shutdown";
if (error != nullptr) *error = "TSI handshaker shutdown";
return TSI_HANDSHAKE_SHUTDOWN;
}
@ -529,7 +528,7 @@ static tsi_result handshaker_next(
size_t* /*bytes_to_send_size*/, tsi_handshaker_result** /*result*/,
tsi_handshaker_on_next_done_cb cb, void* user_data, std::string* error) {
if (self == nullptr || cb == nullptr) {
gpr_log(GPR_ERROR, "Invalid arguments to handshaker_next()");
LOG(ERROR) << "Invalid arguments to handshaker_next()";
if (error != nullptr) *error = "invalid argument";
return TSI_INVALID_ARGUMENT;
}
@ -538,7 +537,7 @@ static tsi_result handshaker_next(
{
grpc_core::MutexLock lock(&handshaker->mu);
if (handshaker->shutdown) {
gpr_log(GPR_INFO, "TSI handshake shutdown");
LOG(INFO) << "TSI handshake shutdown";
if (error != nullptr) *error = "handshake shutdown";
return TSI_HANDSHAKE_SHUTDOWN;
}
@ -569,7 +568,7 @@ static tsi_result handshaker_next(
tsi_result ok = alts_tsi_handshaker_continue_handshaker_next(
handshaker, received_bytes, received_bytes_size, cb, user_data, error);
if (ok != TSI_OK) {
gpr_log(GPR_ERROR, "Failed to schedule ALTS handshaker requests");
LOG(ERROR) << "Failed to schedule ALTS handshaker requests";
return ok;
}
}
@ -651,7 +650,7 @@ tsi_result alts_tsi_handshaker_create(
size_t user_specified_max_frame_size) {
if (handshaker_service_url == nullptr || self == nullptr ||
options == nullptr || (is_client && target_name == nullptr)) {
gpr_log(GPR_ERROR, "Invalid arguments to alts_tsi_handshaker_create()");
LOG(ERROR) << "Invalid arguments to alts_tsi_handshaker_create()";
return TSI_INVALID_ARGUMENT;
}
bool use_dedicated_cq = interested_parties == nullptr;

@ -99,20 +99,20 @@ const auto kMetricResourceUpdatesValid =
"EXPERIMENTAL. A counter of resources received that were considered "
"valid. The counter will be incremented even for resources that "
"have not changed.",
"{resource}",
{kMetricLabelTarget, kMetricLabelXdsServer,
kMetricLabelXdsResourceType},
{}, false);
"{resource}", false)
.Labels(kMetricLabelTarget, kMetricLabelXdsServer,
kMetricLabelXdsResourceType)
.Build();
const auto kMetricResourceUpdatesInvalid =
GlobalInstrumentsRegistry::RegisterUInt64Counter(
"grpc.xds_client.resource_updates_invalid",
"EXPERIMENTAL. A counter of resources received that were considered "
"invalid.",
"{resource}",
{kMetricLabelTarget, kMetricLabelXdsServer,
kMetricLabelXdsResourceType},
{}, false);
"{resource}", false)
.Labels(kMetricLabelTarget, kMetricLabelXdsServer,
kMetricLabelXdsResourceType)
.Build();
const auto kMetricServerFailure =
GlobalInstrumentsRegistry::RegisterUInt64Counter(
@ -121,7 +121,9 @@ const auto kMetricServerFailure =
"unhealthy. A server goes unhealthy when we have a connectivity "
"failure or when the ADS stream fails without seeing a response "
"message, as per gRFC A57.",
"{failure}", {kMetricLabelTarget, kMetricLabelXdsServer}, {}, false);
"{failure}", false)
.Labels(kMetricLabelTarget, kMetricLabelXdsServer)
.Build();
const auto kMetricConnected =
GlobalInstrumentsRegistry::RegisterCallbackInt64Gauge(
@ -132,15 +134,17 @@ const auto kMetricConnected =
"ADS stream fails without seeing a response message, as per gRFC "
"A57. It will be set to 1 when we receive the first response on "
"an ADS stream.",
"{bool}", {kMetricLabelTarget, kMetricLabelXdsServer}, {}, false);
"{bool}", false)
.Labels(kMetricLabelTarget, kMetricLabelXdsServer)
.Build();
const auto kMetricResources =
GlobalInstrumentsRegistry::RegisterCallbackInt64Gauge(
"grpc.xds_client.resources", "EXPERIMENTAL. Number of xDS resources.",
"{resource}",
{kMetricLabelTarget, kMetricLabelXdsAuthority,
kMetricLabelXdsResourceType, kMetricLabelXdsCacheState},
{}, false);
"{resource}", false)
.Labels(kMetricLabelTarget, kMetricLabelXdsAuthority,
kMetricLabelXdsResourceType, kMetricLabelXdsCacheState)
.Build();
} // namespace
@ -316,7 +320,7 @@ GrpcXdsClient::GrpcXdsClient(
[this](CallbackMetricReporter& reporter) {
ReportCallbackMetrics(reporter);
},
{kMetricConnected, kMetricResources})) {}
Duration::Seconds(5), kMetricConnected, kMetricResources)) {}
void GrpcXdsClient::Orphaned() {
registered_metric_callback_.reset();

@ -42,6 +42,7 @@ grpc_cc_library(
external_deps = [
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/status:statusor",
"absl/strings",
"absl/types:optional",

@ -115,6 +115,7 @@ grpc_cc_library(
],
external_deps = [
"absl/base:core_headers",
"absl/log:log",
"absl/numeric:int128",
"absl/strings",
"absl/strings:str_format",
@ -157,6 +158,7 @@ grpc_cc_library(
"absl/container:flat_hash_map",
"absl/functional:any_invocable",
"absl/log:check",
"absl/log:log",
"absl/status",
"absl/status:statusor",
"absl/types:optional",

@ -249,27 +249,35 @@ OpenTelemetryPlugin::CallbackMetricReporter::CallbackMetricReporter(
// that if a particular combination of labels was previously present but
// is no longer present, we won't continue to report it.
for (const auto& handle : key->metrics()) {
grpc_core::Match(
handle,
[&](const grpc_core::GlobalInstrumentsRegistry::
GlobalCallbackInt64GaugeHandle& handle) {
auto& callback_gauge_state =
absl::get<std::unique_ptr<CallbackGaugeState<int64_t>>>(
ot_plugin_->instruments_data_.at(handle.index).instrument);
callback_gauge_state->caches[key].clear();
},
[&](const grpc_core::GlobalInstrumentsRegistry::
GlobalCallbackDoubleGaugeHandle& handle) {
auto& callback_gauge_state =
absl::get<std::unique_ptr<CallbackGaugeState<double>>>(
ot_plugin_->instruments_data_.at(handle.index).instrument);
callback_gauge_state->caches[key].clear();
});
const auto& descriptor =
grpc_core::GlobalInstrumentsRegistry::GetInstrumentDescriptor(handle);
GPR_ASSERT(
descriptor.instrument_type ==
grpc_core::GlobalInstrumentsRegistry::InstrumentType::kCallbackGauge);
switch (descriptor.value_type) {
case grpc_core::GlobalInstrumentsRegistry::ValueType::kInt64: {
auto& callback_gauge_state =
absl::get<std::unique_ptr<CallbackGaugeState<int64_t>>>(
ot_plugin_->instruments_data_.at(handle.index).instrument);
callback_gauge_state->caches[key].clear();
break;
}
case grpc_core::GlobalInstrumentsRegistry::ValueType::kDouble: {
auto& callback_gauge_state =
absl::get<std::unique_ptr<CallbackGaugeState<double>>>(
ot_plugin_->instruments_data_.at(handle.index).instrument);
callback_gauge_state->caches[key].clear();
break;
}
default:
grpc_core::Crash(absl::StrFormat(
"Unknown or unsupported value type: %d", descriptor.value_type));
}
}
}
void OpenTelemetryPlugin::CallbackMetricReporter::Report(
grpc_core::GlobalInstrumentsRegistry::GlobalCallbackInt64GaugeHandle handle,
void OpenTelemetryPlugin::CallbackMetricReporter::ReportInt64(
grpc_core::GlobalInstrumentsRegistry::GlobalInstrumentHandle handle,
int64_t value, absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) {
const auto& instrument_data = ot_plugin_->instruments_data_.at(handle.index);
@ -296,9 +304,8 @@ void OpenTelemetryPlugin::CallbackMetricReporter::Report(
cell.insert_or_assign(std::move(key), value);
}
void OpenTelemetryPlugin::CallbackMetricReporter::Report(
grpc_core::GlobalInstrumentsRegistry::GlobalCallbackDoubleGaugeHandle
handle,
void OpenTelemetryPlugin::CallbackMetricReporter::ReportDouble(
grpc_core::GlobalInstrumentsRegistry::GlobalInstrumentHandle handle,
double value, absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) {
const auto& instrument_data = ot_plugin_->instruments_data_.at(handle.index);
@ -574,8 +581,8 @@ OpenTelemetryPlugin::IsEnabledForChannel(
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.
// 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)};
}
@ -583,7 +590,7 @@ OpenTelemetryPlugin::IsEnabledForServer(
}
void OpenTelemetryPlugin::AddCounter(
grpc_core::GlobalInstrumentsRegistry::GlobalUInt64CounterHandle handle,
grpc_core::GlobalInstrumentsRegistry::GlobalInstrumentHandle 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);
@ -607,7 +614,7 @@ void OpenTelemetryPlugin::AddCounter(
}
void OpenTelemetryPlugin::AddCounter(
grpc_core::GlobalInstrumentsRegistry::GlobalDoubleCounterHandle handle,
grpc_core::GlobalInstrumentsRegistry::GlobalInstrumentHandle 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);
@ -631,7 +638,7 @@ void OpenTelemetryPlugin::AddCounter(
}
void OpenTelemetryPlugin::RecordHistogram(
grpc_core::GlobalInstrumentsRegistry::GlobalUInt64HistogramHandle handle,
grpc_core::GlobalInstrumentsRegistry::GlobalInstrumentHandle 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);
@ -657,7 +664,7 @@ void OpenTelemetryPlugin::RecordHistogram(
}
void OpenTelemetryPlugin::RecordHistogram(
grpc_core::GlobalInstrumentsRegistry::GlobalDoubleHistogramHandle handle,
grpc_core::GlobalInstrumentsRegistry::GlobalInstrumentHandle 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);
@ -691,51 +698,59 @@ void OpenTelemetryPlugin::AddCallback(
grpc_core::MutexLock lock(&mu_);
callback_timestamps_.emplace(callback, grpc_core::Timestamp::InfPast());
for (const auto& handle : callback->metrics()) {
grpc_core::Match(
handle,
[&](const grpc_core::GlobalInstrumentsRegistry::
GlobalCallbackInt64GaugeHandle& handle) {
const auto& instrument_data = instruments_data_.at(handle.index);
if (absl::holds_alternative<Disabled>(instrument_data.instrument)) {
// This instrument is disabled.
return;
}
auto* callback_gauge_state =
absl::get_if<std::unique_ptr<CallbackGaugeState<int64_t>>>(
&instrument_data.instrument);
CHECK_NE(callback_gauge_state, nullptr);
(*callback_gauge_state)
->caches.emplace(callback,
CallbackGaugeState<int64_t>::Cache{});
if (!std::exchange((*callback_gauge_state)->ot_callback_registered,
true)) {
gauges_that_need_to_add_callback.push_back(
callback_gauge_state->get());
}
},
[&](const grpc_core::GlobalInstrumentsRegistry::
GlobalCallbackDoubleGaugeHandle& handle) {
const auto& instrument_data = instruments_data_.at(handle.index);
if (absl::holds_alternative<Disabled>(instrument_data.instrument)) {
// This instrument is disabled.
return;
}
auto* callback_gauge_state =
absl::get_if<std::unique_ptr<CallbackGaugeState<double>>>(
&instrument_data.instrument);
CHECK_NE(callback_gauge_state, nullptr);
(*callback_gauge_state)
->caches.emplace(callback, CallbackGaugeState<double>::Cache{});
if (!std::exchange((*callback_gauge_state)->ot_callback_registered,
true)) {
gauges_that_need_to_add_callback.push_back(
callback_gauge_state->get());
}
});
const auto& descriptor =
grpc_core::GlobalInstrumentsRegistry::GetInstrumentDescriptor(handle);
GPR_ASSERT(
descriptor.instrument_type ==
grpc_core::GlobalInstrumentsRegistry::InstrumentType::kCallbackGauge);
switch (descriptor.value_type) {
case grpc_core::GlobalInstrumentsRegistry::ValueType::kInt64: {
const auto& instrument_data = instruments_data_.at(handle.index);
if (absl::holds_alternative<Disabled>(instrument_data.instrument)) {
// This instrument is disabled.
continue;
}
auto* callback_gauge_state =
absl::get_if<std::unique_ptr<CallbackGaugeState<int64_t>>>(
&instrument_data.instrument);
CHECK_NE(callback_gauge_state, nullptr);
(*callback_gauge_state)
->caches.emplace(callback, CallbackGaugeState<int64_t>::Cache{});
if (!std::exchange((*callback_gauge_state)->ot_callback_registered,
true)) {
gauges_that_need_to_add_callback.push_back(
callback_gauge_state->get());
}
break;
}
case grpc_core::GlobalInstrumentsRegistry::ValueType::kDouble: {
const auto& instrument_data = instruments_data_.at(handle.index);
if (absl::holds_alternative<Disabled>(instrument_data.instrument)) {
// This instrument is disabled.
continue;
}
auto* callback_gauge_state =
absl::get_if<std::unique_ptr<CallbackGaugeState<double>>>(
&instrument_data.instrument);
CHECK_NE(callback_gauge_state, nullptr);
(*callback_gauge_state)
->caches.emplace(callback, CallbackGaugeState<double>::Cache{});
if (!std::exchange((*callback_gauge_state)->ot_callback_registered,
true)) {
gauges_that_need_to_add_callback.push_back(
callback_gauge_state->get());
}
break;
}
default:
grpc_core::Crash(absl::StrFormat(
"Unknown or unsupported value type: %d", descriptor.value_type));
}
}
}
// AddCallback internally grabs OpenTelemetry's observable_registry's lock. So
// we need to call it without our plugin lock otherwise we may deadlock.
// AddCallback internally grabs OpenTelemetry's observable_registry's
// lock. So we need to call it without our plugin lock otherwise we may
// deadlock.
for (const auto& gauge : gauges_that_need_to_add_callback) {
grpc_core::Match(
gauge,
@ -759,50 +774,59 @@ void OpenTelemetryPlugin::RemoveCallback(
grpc_core::MutexLock lock(&mu_);
callback_timestamps_.erase(callback);
for (const auto& handle : callback->metrics()) {
grpc_core::Match(
handle,
[&](const grpc_core::GlobalInstrumentsRegistry::
GlobalCallbackInt64GaugeHandle& handle) {
const auto& instrument_data = instruments_data_.at(handle.index);
if (absl::holds_alternative<Disabled>(instrument_data.instrument)) {
// This instrument is disabled.
return;
}
auto* callback_gauge_state =
absl::get_if<std::unique_ptr<CallbackGaugeState<int64_t>>>(
&instrument_data.instrument);
CHECK_NE(callback_gauge_state, nullptr);
CHECK((*callback_gauge_state)->ot_callback_registered);
CHECK_EQ((*callback_gauge_state)->caches.erase(callback), 1u);
if ((*callback_gauge_state)->caches.empty()) {
gauges_that_need_to_remove_callback.push_back(
callback_gauge_state->get());
(*callback_gauge_state)->ot_callback_registered = false;
}
},
[&](const grpc_core::GlobalInstrumentsRegistry::
GlobalCallbackDoubleGaugeHandle& handle) {
const auto& instrument_data = instruments_data_.at(handle.index);
if (absl::holds_alternative<Disabled>(instrument_data.instrument)) {
// This instrument is disabled.
return;
}
auto* callback_gauge_state =
absl::get_if<std::unique_ptr<CallbackGaugeState<double>>>(
&instrument_data.instrument);
CHECK_NE(callback_gauge_state, nullptr);
CHECK((*callback_gauge_state)->ot_callback_registered);
CHECK_EQ((*callback_gauge_state)->caches.erase(callback), 1u);
if ((*callback_gauge_state)->caches.empty()) {
gauges_that_need_to_remove_callback.push_back(
callback_gauge_state->get());
(*callback_gauge_state)->ot_callback_registered = false;
}
});
const auto& descriptor =
grpc_core::GlobalInstrumentsRegistry::GetInstrumentDescriptor(handle);
GPR_ASSERT(
descriptor.instrument_type ==
grpc_core::GlobalInstrumentsRegistry::InstrumentType::kCallbackGauge);
switch (descriptor.value_type) {
case grpc_core::GlobalInstrumentsRegistry::ValueType::kInt64: {
const auto& instrument_data = instruments_data_.at(handle.index);
if (absl::holds_alternative<Disabled>(instrument_data.instrument)) {
// This instrument is disabled.
continue;
}
auto* callback_gauge_state =
absl::get_if<std::unique_ptr<CallbackGaugeState<int64_t>>>(
&instrument_data.instrument);
CHECK_NE(callback_gauge_state, nullptr);
CHECK((*callback_gauge_state)->ot_callback_registered);
CHECK_EQ((*callback_gauge_state)->caches.erase(callback), 1u);
if ((*callback_gauge_state)->caches.empty()) {
gauges_that_need_to_remove_callback.push_back(
callback_gauge_state->get());
(*callback_gauge_state)->ot_callback_registered = false;
}
break;
}
case grpc_core::GlobalInstrumentsRegistry::ValueType::kDouble: {
const auto& instrument_data = instruments_data_.at(handle.index);
if (absl::holds_alternative<Disabled>(instrument_data.instrument)) {
// This instrument is disabled.
continue;
}
auto* callback_gauge_state =
absl::get_if<std::unique_ptr<CallbackGaugeState<double>>>(
&instrument_data.instrument);
CHECK_NE(callback_gauge_state, nullptr);
CHECK((*callback_gauge_state)->ot_callback_registered);
CHECK_EQ((*callback_gauge_state)->caches.erase(callback), 1u);
if ((*callback_gauge_state)->caches.empty()) {
gauges_that_need_to_remove_callback.push_back(
callback_gauge_state->get());
(*callback_gauge_state)->ot_callback_registered = false;
}
break;
}
default:
grpc_core::Crash(absl::StrFormat(
"Unknown or unsupported value type: %d", descriptor.value_type));
}
}
}
// RemoveCallback internally grabs OpenTelemetry's observable_registry's lock.
// So we need to call it without our plugin lock otherwise we may deadlock.
// RemoveCallback internally grabs OpenTelemetry's observable_registry's
// lock. So we need to call it without our plugin lock otherwise we may
// deadlock.
for (const auto& gauge : gauges_that_need_to_remove_callback) {
grpc_core::Match(
gauge,
@ -842,7 +866,8 @@ void OpenTelemetryPlugin::CallbackGaugeState<ValueType>::Observe(
}
}
// OpenTelemetry calls our callback with its observable_registry's lock held.
// OpenTelemetry calls our callback with its observable_registry's lock
// held.
template <typename ValueType>
void OpenTelemetryPlugin::CallbackGaugeState<ValueType>::CallbackGaugeCallback(
opentelemetry::metrics::ObserverResult result, void* arg) {

@ -343,22 +343,20 @@ class OpenTelemetryPlugin : public grpc_core::StatsPlugin {
grpc_core::RegisteredMetricCallback* key)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(ot_plugin->mu_);
void Report(
grpc_core::GlobalInstrumentsRegistry::GlobalCallbackInt64GaugeHandle
handle,
private:
void ReportInt64(
grpc_core::GlobalInstrumentsRegistry::GlobalInstrumentHandle handle,
int64_t value, absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(
CallbackGaugeState<int64_t>::ot_plugin->mu_) override;
void Report(
grpc_core::GlobalInstrumentsRegistry::GlobalCallbackDoubleGaugeHandle
handle,
void ReportDouble(
grpc_core::GlobalInstrumentsRegistry::GlobalInstrumentHandle handle,
double value, absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(
CallbackGaugeState<double>::ot_plugin->mu_) override;
private:
OpenTelemetryPlugin* ot_plugin_;
grpc_core::RegisteredMetricCallback* key_;
};
@ -380,19 +378,19 @@ class OpenTelemetryPlugin : public grpc_core::StatsPlugin {
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,
grpc_core::GlobalInstrumentsRegistry::GlobalInstrumentHandle 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,
grpc_core::GlobalInstrumentsRegistry::GlobalInstrumentHandle 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,
grpc_core::GlobalInstrumentsRegistry::GlobalInstrumentHandle 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,
grpc_core::GlobalInstrumentsRegistry::GlobalInstrumentHandle handle,
double value, absl::Span<const absl::string_view> label_values,
absl::Span<const absl::string_view> optional_values) override;
void AddCallback(grpc_core::RegisteredMetricCallback* callback)

@ -31,6 +31,7 @@
#include <grpc/impl/channel_arg_names.h>
#include <grpc/impl/compression_types.h>
#include <grpc/support/log.h>
#include <grpc/support/port_platform.h>
#include <grpc/support/sync.h>
#include <grpc/support/workaround_list.h>
#include <grpcpp/completion_queue.h>
@ -47,11 +48,38 @@
#include <grpcpp/support/channel_arguments.h>
#include <grpcpp/support/server_interceptor.h>
#include "src/core/ext/transport/chttp2/server/chttp2_server.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/server/server.h"
#include "src/cpp/server/external_connection_acceptor_impl.h"
namespace grpc {
namespace {
// A PIMPL wrapper class that owns the only ref to the passive listener
// implementation. This is returned to the application.
class PassiveListenerOwner final
: public grpc_core::experimental::PassiveListener {
public:
explicit PassiveListenerOwner(std::shared_ptr<PassiveListener> listener)
: listener_(std::move(listener)) {}
absl::Status AcceptConnectedEndpoint(
std::unique_ptr<grpc_event_engine::experimental::EventEngine::Endpoint>
endpoint) override {
return listener_->AcceptConnectedEndpoint(std::move(endpoint));
}
absl::Status AcceptConnectedFd(int fd) override {
return listener_->AcceptConnectedFd(fd);
}
private:
std::shared_ptr<PassiveListener> listener_;
};
} // namespace
static std::vector<std::unique_ptr<ServerBuilderPlugin> (*)()>*
g_plugin_factory_list;
@ -225,6 +253,18 @@ ServerBuilder& ServerBuilder::SetResourceQuota(
return *this;
}
ServerBuilder& ServerBuilder::experimental_type::AddPassiveListener(
std::shared_ptr<grpc::ServerCredentials> creds,
std::unique_ptr<experimental::PassiveListener>& passive_listener) {
auto core_passive_listener =
std::make_shared<grpc_core::experimental::PassiveListenerImpl>();
builder_->unstarted_passive_listeners_.emplace_back(core_passive_listener,
std::move(creds));
passive_listener =
std::make_unique<PassiveListenerOwner>(std::move(core_passive_listener));
return *builder_;
}
ServerBuilder& ServerBuilder::AddListeningPort(
const std::string& addr_uri, std::shared_ptr<ServerCredentials> creds,
int* selected_port) {
@ -398,6 +438,26 @@ std::unique_ptr<grpc::Server> ServerBuilder::BuildAndStart() {
cq->RegisterServer(server.get());
}
for (auto& unstarted_listener : unstarted_passive_listeners_) {
has_frequently_polled_cqs = true;
auto passive_listener = unstarted_listener.passive_listener.lock();
auto* core_server = grpc_core::Server::FromC(server->c_server());
if (passive_listener != nullptr) {
auto* creds = unstarted_listener.credentials->c_creds();
if (creds == nullptr) {
gpr_log(GPR_ERROR, "Credentials missing for PassiveListener");
return nullptr;
}
auto success = grpc_server_add_passive_listener(
core_server, creds, std::move(passive_listener));
if (!success.ok()) {
gpr_log(GPR_ERROR, "Failed to create a passive listener: %s",
success.ToString().c_str());
return nullptr;
}
}
}
if (!has_frequently_polled_cqs) {
gpr_log(GPR_ERROR,
"At least one of the completion queues must be frequently polled");

@ -736,6 +736,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/transport/call_spine.cc',
'src/core/lib/transport/connectivity_state.cc',
'src/core/lib/transport/error_utils.cc',
'src/core/lib/transport/interception_chain.cc',
'src/core/lib/transport/message.cc',
'src/core/lib/transport/metadata.cc',
'src/core/lib/transport/metadata_batch.cc',

@ -0,0 +1,28 @@
%YAML 1.2
--- |
# Copyright 2021 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.
FROM gcc:7
RUN apt-get update && apt-get install -y curl git time wget zip && apt-get clean
<%include file="../../git_avoid_dubious_ownership_error.include"/>
<%include file="../../run_tests_python_deps.include"/>
<%include file="../../cxx_test_deps.include"/>
<%include file="../../cmake.include"/>
<%include file="../../ccache_old.include"/>
<%include file="../../run_tests_addons.include"/>
# Define the default command.
CMD ["bash"]

@ -41,6 +41,7 @@ grpc_cc_test(
name = "parse_address_test",
srcs = ["parse_address_test.cc"],
external_deps = [
"absl/log:log",
"absl/strings",
"gtest",
],
@ -69,7 +70,10 @@ grpc_fuzzer(
grpc_cc_test(
name = "parse_address_with_named_scope_id_test",
srcs = ["parse_address_with_named_scope_id_test.cc"],
external_deps = ["gtest"],
external_deps = [
"absl/log:log",
"gtest",
],
language = "C++",
tags = ["no_windows"],
uses_event_engine = False,

@ -34,12 +34,12 @@
#include <string>
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/strings/match.h"
#include "gtest/gtest.h"
#include <grpc/grpc.h>
#include <grpc/support/log.h>
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/iomgr/port.h"
@ -53,7 +53,7 @@ static void test_grpc_parse_unix(const char* uri_text, const char* pathname) {
grpc_core::ExecCtx exec_ctx;
absl::StatusOr<grpc_core::URI> uri = grpc_core::URI::Parse(uri_text);
if (!uri.ok()) {
gpr_log(GPR_ERROR, "%s", uri.status().ToString().c_str());
LOG(ERROR) << uri.status();
ASSERT_TRUE(uri.ok());
}
grpc_resolved_address addr;
@ -70,7 +70,7 @@ static void test_grpc_parse_unix_abstract(const char* uri_text,
grpc_core::ExecCtx exec_ctx;
absl::StatusOr<grpc_core::URI> uri = grpc_core::URI::Parse(uri_text);
if (!uri.ok()) {
gpr_log(GPR_ERROR, "%s", uri.status().ToString().c_str());
LOG(ERROR) << uri.status();
ASSERT_TRUE(uri.ok());
}
grpc_resolved_address addr;
@ -98,7 +98,7 @@ static void test_grpc_parse_vsock(const char* uri_text, uint32_t cid,
grpc_core::ExecCtx exec_ctx;
absl::StatusOr<grpc_core::URI> uri = grpc_core::URI::Parse(uri_text);
if (!uri.ok()) {
gpr_log(GPR_ERROR, "%s", uri.status().ToString().c_str());
LOG(ERROR) << uri.status();
ASSERT_TRUE(uri.ok());
}
grpc_resolved_address addr;
@ -122,7 +122,7 @@ static void test_grpc_parse_ipv4(const char* uri_text, const char* host,
grpc_core::ExecCtx exec_ctx;
absl::StatusOr<grpc_core::URI> uri = grpc_core::URI::Parse(uri_text);
if (!uri.ok()) {
gpr_log(GPR_ERROR, "%s", uri.status().ToString().c_str());
LOG(ERROR) << uri.status();
ASSERT_TRUE(uri.ok());
}
grpc_resolved_address addr;
@ -142,7 +142,7 @@ static void test_grpc_parse_ipv6(const char* uri_text, const char* host,
grpc_core::ExecCtx exec_ctx;
absl::StatusOr<grpc_core::URI> uri = grpc_core::URI::Parse(uri_text);
if (!uri.ok()) {
gpr_log(GPR_ERROR, "%s", uri.status().ToString().c_str());
LOG(ERROR) << uri.status();
ASSERT_TRUE(uri.ok());
}
grpc_resolved_address addr;
@ -162,7 +162,7 @@ static void test_grpc_parse_ipv6_invalid(const char* uri_text) {
grpc_core::ExecCtx exec_ctx;
absl::StatusOr<grpc_core::URI> uri = grpc_core::URI::Parse(uri_text);
if (!uri.ok()) {
gpr_log(GPR_ERROR, "%s", uri.status().ToString().c_str());
LOG(ERROR) << uri.status();
ASSERT_TRUE(uri.ok());
}
grpc_resolved_address addr;

@ -28,13 +28,13 @@
#include <string>
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_format.h"
#include "gtest/gtest.h"
#include <grpc/grpc.h>
#include <grpc/support/log.h>
#include "src/core/lib/address_utils/parse_address.h"
#include "src/core/lib/gprpp/crash.h"
@ -114,10 +114,8 @@ TEST(ParseAddressWithNamedScopeIdTest, MainTest) {
// system recognizes, and then use that for the test.
for (size_t i = 1; i < 65536; i++) {
if (if_indextoname(i, arbitrary_interface_name) != nullptr) {
gpr_log(GPR_DEBUG,
"Found interface at index %" PRIuPTR
" named %s. Will use this for the test",
i, arbitrary_interface_name);
VLOG(2) << "Found interface at index " << i << " named "
<< arbitrary_interface_name << ". Will use this for the test";
break;
}
}
@ -127,9 +125,8 @@ TEST(ParseAddressWithNamedScopeIdTest, MainTest) {
struct sockaddr_in6 result_from_getaddrinfo =
resolve_with_gettaddrinfo(target.c_str());
// Run the test
gpr_log(GPR_DEBUG,
"Run test_grpc_parse_ipv6_parity_with_getaddrinfo with target: %s",
target.c_str());
VLOG(2) << "Run test_grpc_parse_ipv6_parity_with_getaddrinfo with target: "
<< target;
test_grpc_parse_ipv6_parity_with_getaddrinfo(target.c_str(),
result_from_getaddrinfo);
// Cleanup

@ -22,11 +22,11 @@
#include <limits.h>
#include "absl/log/check.h"
#include "absl/log/log.h"
#include <grpc/impl/channel_arg_names.h>
#include <grpc/slice_buffer.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
#include <grpc/support/time.h>
@ -111,11 +111,11 @@ void grpc_run_client_side_validator(grpc_bad_client_arg* arg, uint32_t flags,
hex = gpr_dump(arg->client_payload, arg->client_payload_length,
GPR_DUMP_HEX | GPR_DUMP_ASCII);
// Add a debug log
gpr_log(GPR_INFO, "TEST: %s", hex);
LOG(INFO) << "TEST: " << hex;
gpr_free(hex);
} else {
gpr_log(GPR_INFO, "TEST: (%" PRIdPTR " byte long string)",
arg->client_payload_length);
LOG(INFO) << "TEST: (" << arg->client_payload_length
<< " byte long string)";
}
grpc_slice slice = grpc_slice_from_copied_buffer(arg->client_payload,
@ -171,9 +171,8 @@ void grpc_run_client_side_validator(grpc_bad_client_arg* arg, uint32_t flags,
.type == GRPC_QUEUE_TIMEOUT);
} while (!gpr_event_get(&read_done_event));
if (arg->client_validator(&incoming, arg->client_validator_arg)) break;
gpr_log(GPR_INFO,
"client validator failed; trying additional read "
"in case we didn't get all the data");
LOG(INFO) << "client validator failed; trying additional read "
"in case we didn't get all the data";
}
grpc_slice_buffer_destroy(&incoming);
}
@ -317,7 +316,7 @@ bool rst_stream_client_validator(grpc_slice_buffer* incoming, void* /*arg*/) {
*p++ == 0 || *p++ == 0 || *p++ == 0 || *p == 0 || *p == 11;
if (!success) {
gpr_log(GPR_INFO, "client expected RST_STREAM frame, not found");
LOG(INFO) << "client expected RST_STREAM frame, not found";
}
grpc_slice_buffer_destroy(&last_frame_buffer);

@ -44,6 +44,10 @@ def grpc_bad_client_tests():
hdrs = ["bad_client.h"],
language = "C++",
testonly = 1,
external_deps = [
"absl/log:check",
"absl/log:log",
],
deps = [
"//test/core/test_util:grpc_test_util",
"//:grpc",
@ -51,9 +55,6 @@ def grpc_bad_client_tests():
"//test/core/end2end:cq_verifier",
"//:grpc_http_filters",
],
external_deps = [
"absl/log:check",
],
)
for t, topt in BAD_CLIENT_TESTS.items():
grpc_cc_test(

@ -23,7 +23,10 @@ grpc_cc_binary(
srcs = [
"close_fd_test.cc",
],
external_deps = ["absl/log:check"],
external_deps = [
"absl/log:check",
"absl/log:log",
],
language = "C++",
tags = ["no_windows"],
deps = [

@ -24,6 +24,7 @@
#include <stdint.h>
#include "absl/log/check.h"
#include "absl/log/log.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_format.h"
@ -53,7 +54,6 @@
#include <grpc/byte_buffer.h>
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
#include "src/core/lib/gprpp/crash.h"
@ -225,8 +225,8 @@ static void _test_close_before_server_recv(fd_type fdtype) {
grpc_raw_byte_buffer_create(&request_payload_slice, 1);
grpc_byte_buffer* response_payload =
grpc_raw_byte_buffer_create(&response_payload_slice, 1);
gpr_log(GPR_INFO, "Running test: test_close_%s_before_server_recv",
fd_type_str(fdtype));
LOG(INFO) << "Running test: test_close_" << fd_type_str(fdtype)
<< "_before_server_recv";
test_init();
grpc_op ops[6];
@ -399,8 +399,8 @@ static void _test_close_before_server_send(fd_type fdtype) {
grpc_raw_byte_buffer_create(&request_payload_slice, 1);
grpc_byte_buffer* response_payload =
grpc_raw_byte_buffer_create(&response_payload_slice, 1);
gpr_log(GPR_INFO, "Running test: test_close_%s_before_server_send",
fd_type_str(fdtype));
LOG(INFO) << "Running test: test_close_" << fd_type_str(fdtype)
<< "_before_server_send";
test_init();
grpc_op ops[6];
@ -596,8 +596,8 @@ static void _test_close_before_client_send(fd_type fdtype) {
grpc_raw_byte_buffer_create(&request_payload_slice, 1);
grpc_byte_buffer* response_payload =
grpc_raw_byte_buffer_create(&response_payload_slice, 1);
gpr_log(GPR_INFO, "Running test: test_close_%s_before_client_send",
fd_type_str(fdtype));
LOG(INFO) << "Running test: test_close_" << fd_type_str(fdtype)
<< "_before_client_send";
test_init();
grpc_op ops[6];

@ -35,6 +35,7 @@ def grpc_bad_ssl_tests():
hdrs = ["server_common.h"],
external_deps = [
"absl/log:check",
"absl/log:log",
],
deps = [
"//test/core/test_util:grpc_test_util",

@ -21,8 +21,8 @@
#include <signal.h>
#include "absl/log/check.h"
#include "absl/log/log.h"
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include "test/core/test_util/cmdline.h"
@ -74,7 +74,7 @@ void bad_ssl_run(grpc_server* server) {
signal(SIGINT, sigint_handler);
while (!shutdown_finished) {
if (got_sigint && !shutdown_started) {
gpr_log(GPR_INFO, "Shutting down due to SIGINT");
LOG(INFO) << "Shutting down due to SIGINT";
shutdown_cq = grpc_completion_queue_create_for_pluck(nullptr);
grpc_server_shutdown_and_notify(server, shutdown_cq, nullptr);
CHECK(grpc_completion_queue_pluck(shutdown_cq, nullptr,

@ -37,6 +37,7 @@ grpc_cc_test(
srcs = ["channel_args_test.cc"],
external_deps = [
"absl/log:check",
"absl/log:log",
"gtest",
],
language = "C++",
@ -149,6 +150,7 @@ grpc_cc_test(
name = "metrics_test",
srcs = ["metrics_test.cc"],
external_deps = [
"absl/log:log",
"gtest",
],
language = "C++",

@ -21,6 +21,7 @@
#include <string.h>
#include "absl/log/check.h"
#include "absl/log/log.h"
#include "gtest/gtest.h"
#include <grpc/credentials.h>
@ -28,7 +29,6 @@
#include <grpc/grpc_security.h>
#include <grpc/impl/channel_arg_names.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/gprpp/notification.h"
@ -272,7 +272,7 @@ struct fake_class {
};
static void* fake_pointer_arg_copy(void* arg) {
gpr_log(GPR_DEBUG, "fake_pointer_arg_copy");
VLOG(2) << "fake_pointer_arg_copy";
fake_class* fc = static_cast<fake_class*>(arg);
fake_class* new_fc = static_cast<fake_class*>(gpr_malloc(sizeof(fake_class)));
new_fc->foo = fc->foo;
@ -280,7 +280,7 @@ static void* fake_pointer_arg_copy(void* arg) {
}
static void fake_pointer_arg_destroy(void* arg) {
gpr_log(GPR_DEBUG, "fake_pointer_arg_destroy");
VLOG(2) << "fake_pointer_arg_destroy";
fake_class* fc = static_cast<fake_class*>(arg);
gpr_free(fc);
}

@ -16,10 +16,7 @@
#include <memory>
#include "absl/container/flat_hash_map.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "absl/log/log.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
@ -40,15 +37,15 @@ class MetricsTest : public ::testing::Test {
};
TEST_F(MetricsTest, UInt64Counter) {
const absl::string_view kLabelKeys[] = {"label_key_1", "label_key_2"};
const absl::string_view kOptionalLabelKeys[] = {"optional_label_key_1",
"optional_label_key_2"};
auto uint64_counter_handle = GlobalInstrumentsRegistry::RegisterUInt64Counter(
"uint64_counter", "A simple uint64 counter.", "unit", kLabelKeys,
kOptionalLabelKeys, true);
constexpr absl::string_view kLabelValues[] = {"label_value_1",
"label_value_2"};
constexpr absl::string_view kOptionalLabelValues[] = {
auto uint64_counter_handle =
GlobalInstrumentsRegistry::RegisterUInt64Counter(
"uint64_counter", "A simple uint64 counter.", "unit", true)
.Labels("label_key_1", "label_key_2")
.OptionalLabels("optional_label_key_1", "optional_label_key_2")
.Build();
std::array<absl::string_view, 2> kLabelValues = {"label_value_1",
"label_value_2"};
std::array<absl::string_view, 2> kOptionalLabelValues = {
"optional_label_value_1", "optional_label_value_2"};
constexpr absl::string_view kDomain1To4 = "domain1.domain2.domain3.domain4";
constexpr absl::string_view kDomain2To4 = "domain2.domain3.domain4";
@ -58,34 +55,37 @@ TEST_F(MetricsTest, UInt64Counter) {
auto plugin3 = MakeStatsPluginForTarget(kDomain3To4);
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPluginChannelScope(kDomain1To4, ""))
.AddCounter(uint64_counter_handle, 1, kLabelValues, kOptionalLabelValues);
.AddCounter(uint64_counter_handle, uint64_t(1), kLabelValues,
kOptionalLabelValues);
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPluginChannelScope(kDomain2To4, ""))
.AddCounter(uint64_counter_handle, 2, kLabelValues, kOptionalLabelValues);
.AddCounter(uint64_counter_handle, uint64_t(2), kLabelValues,
kOptionalLabelValues);
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPluginChannelScope(kDomain3To4, ""))
.AddCounter(uint64_counter_handle, 3, kLabelValues, kOptionalLabelValues);
EXPECT_THAT(plugin1->GetCounterValue(uint64_counter_handle, kLabelValues,
kOptionalLabelValues),
.AddCounter(uint64_counter_handle, uint64_t(3), kLabelValues,
kOptionalLabelValues);
EXPECT_THAT(plugin1->GetUInt64CounterValue(
uint64_counter_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(1));
EXPECT_THAT(plugin2->GetCounterValue(uint64_counter_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin2->GetUInt64CounterValue(
uint64_counter_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(3));
EXPECT_THAT(plugin3->GetCounterValue(uint64_counter_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin3->GetUInt64CounterValue(
uint64_counter_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(6));
}
TEST_F(MetricsTest, DoubleCounter) {
const absl::string_view kLabelKeys[] = {"label_key_1", "label_key_2"};
const absl::string_view kOptionalLabelKeys[] = {"optional_label_key_1",
"optional_label_key_2"};
auto double_counter_handle = GlobalInstrumentsRegistry::RegisterDoubleCounter(
"double_counter", "A simple double counter.", "unit", kLabelKeys,
kOptionalLabelKeys, true);
constexpr absl::string_view kLabelValues[] = {"label_value_1",
"label_value_2"};
constexpr absl::string_view kOptionalLabelValues[] = {
auto double_counter_handle =
GlobalInstrumentsRegistry::RegisterDoubleCounter(
"double_counter", "A simple double counter.", "unit", true)
.Labels("label_key_1", "label_key_2")
.OptionalLabels("optional_label_key_1", "optional_label_key_2")
.Build();
std::array<absl::string_view, 2> kLabelValues = {"label_value_1",
"label_value_2"};
std::array<absl::string_view, 2> kOptionalLabelValues = {
"optional_label_value_1", "optional_label_value_2"};
constexpr absl::string_view kDomain1To4 = "domain1.domain2.domain3.domain4";
constexpr absl::string_view kDomain2To4 = "domain2.domain3.domain4";
@ -105,28 +105,27 @@ TEST_F(MetricsTest, DoubleCounter) {
StatsPluginChannelScope(kDomain3To4, ""))
.AddCounter(double_counter_handle, 3.45, kLabelValues,
kOptionalLabelValues);
EXPECT_THAT(plugin1->GetCounterValue(double_counter_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin1->GetDoubleCounterValue(
double_counter_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(1.23));
EXPECT_THAT(plugin2->GetCounterValue(double_counter_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin2->GetDoubleCounterValue(
double_counter_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(3.57));
EXPECT_THAT(plugin3->GetCounterValue(double_counter_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin3->GetDoubleCounterValue(
double_counter_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(7.02));
}
TEST_F(MetricsTest, UInt64Histogram) {
const absl::string_view kLabelKeys[] = {"label_key_1", "label_key_2"};
const absl::string_view kOptionalLabelKeys[] = {"optional_label_key_1",
"optional_label_key_2"};
auto uint64_histogram_handle =
GlobalInstrumentsRegistry::RegisterUInt64Histogram(
"uint64_histogram", "A simple uint64 histogram.", "unit", kLabelKeys,
kOptionalLabelKeys, true);
constexpr absl::string_view kLabelValues[] = {"label_value_1",
"label_value_2"};
constexpr absl::string_view kOptionalLabelValues[] = {
"uint64_histogram", "A simple uint64 histogram.", "unit", true)
.Labels("label_key_1", "label_key_2")
.OptionalLabels("optional_label_key_1", "optional_label_key_2")
.Build();
std::array<absl::string_view, 2> kLabelValues = {"label_value_1",
"label_value_2"};
std::array<absl::string_view, 2> kOptionalLabelValues = {
"optional_label_value_1", "optional_label_value_2"};
constexpr absl::string_view kDomain1To4 = "domain1.domain2.domain3.domain4";
constexpr absl::string_view kDomain2To4 = "domain2.domain3.domain4";
@ -136,38 +135,37 @@ TEST_F(MetricsTest, UInt64Histogram) {
auto plugin3 = MakeStatsPluginForTarget(kDomain3To4);
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPluginChannelScope(kDomain1To4, ""))
.RecordHistogram(uint64_histogram_handle, 1, kLabelValues,
.RecordHistogram(uint64_histogram_handle, uint64_t(1), kLabelValues,
kOptionalLabelValues);
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPluginChannelScope(kDomain2To4, ""))
.RecordHistogram(uint64_histogram_handle, 2, kLabelValues,
.RecordHistogram(uint64_histogram_handle, uint64_t(2), kLabelValues,
kOptionalLabelValues);
GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPluginChannelScope(kDomain3To4, ""))
.RecordHistogram(uint64_histogram_handle, 3, kLabelValues,
.RecordHistogram(uint64_histogram_handle, uint64_t(3), kLabelValues,
kOptionalLabelValues);
EXPECT_THAT(plugin1->GetHistogramValue(uint64_histogram_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin1->GetUInt64HistogramValue(
uint64_histogram_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(::testing::UnorderedElementsAre(1)));
EXPECT_THAT(plugin2->GetHistogramValue(uint64_histogram_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin2->GetUInt64HistogramValue(
uint64_histogram_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(::testing::UnorderedElementsAre(1, 2)));
EXPECT_THAT(plugin3->GetHistogramValue(uint64_histogram_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin3->GetUInt64HistogramValue(
uint64_histogram_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(::testing::UnorderedElementsAre(1, 2, 3)));
}
TEST_F(MetricsTest, DoubleHistogram) {
const absl::string_view kLabelKeys[] = {"label_key_1", "label_key_2"};
const absl::string_view kOptionalLabelKeys[] = {"optional_label_key_1",
"optional_label_key_2"};
auto double_histogram_handle =
GlobalInstrumentsRegistry::RegisterDoubleHistogram(
"double_histogram", "A simple double histogram.", "unit", kLabelKeys,
kOptionalLabelKeys, true);
constexpr absl::string_view kLabelValues[] = {"label_value_1",
"label_value_2"};
constexpr absl::string_view kOptionalLabelValues[] = {
"double_histogram", "A simple double histogram.", "unit", true)
.Labels("label_key_1", "label_key_2")
.OptionalLabels("optional_label_key_1", "optional_label_key_2")
.Build();
std::array<absl::string_view, 2> kLabelValues = {"label_value_1",
"label_value_2"};
std::array<absl::string_view, 2> kOptionalLabelValues = {
"optional_label_value_1", "optional_label_value_2"};
constexpr absl::string_view kDomain1To4 = "domain1.domain2.domain3.domain4";
constexpr absl::string_view kDomain2To4 = "domain2.domain3.domain4";
@ -187,31 +185,30 @@ TEST_F(MetricsTest, DoubleHistogram) {
StatsPluginChannelScope(kDomain3To4, ""))
.RecordHistogram(double_histogram_handle, 3.45, kLabelValues,
kOptionalLabelValues);
EXPECT_THAT(plugin1->GetHistogramValue(double_histogram_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin1->GetDoubleHistogramValue(
double_histogram_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(::testing::UnorderedElementsAre(1.23)));
EXPECT_THAT(plugin2->GetHistogramValue(double_histogram_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin2->GetDoubleHistogramValue(
double_histogram_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(::testing::UnorderedElementsAre(1.23, 2.34)));
EXPECT_THAT(
plugin3->GetHistogramValue(double_histogram_handle, kLabelValues,
kOptionalLabelValues),
plugin3->GetDoubleHistogramValue(double_histogram_handle, kLabelValues,
kOptionalLabelValues),
::testing::Optional(::testing::UnorderedElementsAre(1.23, 2.34, 3.45)));
}
TEST_F(MetricsTest, Int64CallbackGauge) {
const absl::string_view kLabelKeys[] = {"label_key_1", "label_key_2"};
const absl::string_view kOptionalLabelKeys[] = {"optional_label_key_1",
"optional_label_key_2"};
auto int64_gauge_handle =
GlobalInstrumentsRegistry::RegisterCallbackInt64Gauge(
"int64_gauge", "A simple int64 gauge.", "unit", kLabelKeys,
kOptionalLabelKeys, true);
constexpr absl::string_view kLabelValues[] = {"label_value_1",
"label_value_2"};
constexpr absl::string_view kLabelValues2[] = {"label_value_3",
"label_value_2"};
constexpr absl::string_view kOptionalLabelValues[] = {
"int64_gauge", "A simple int64 gauge.", "unit", true)
.Labels("label_key_1", "label_key_2")
.OptionalLabels("optional_label_key_1", "optional_label_key_2")
.Build();
std::array<absl::string_view, 2> kLabelValues = {"label_value_1",
"label_value_2"};
std::array<absl::string_view, 2> kLabelValues2 = {"label_value_3",
"label_value_2"};
std::array<absl::string_view, 2> kOptionalLabelValues = {
"optional_label_value_1", "optional_label_value_2"};
constexpr absl::string_view kDomain1To4 = "domain1.domain2.domain3.domain4";
constexpr absl::string_view kDomain2To4 = "domain2.domain3.domain4";
@ -221,184 +218,184 @@ TEST_F(MetricsTest, Int64CallbackGauge) {
auto plugin3 = MakeStatsPluginForTarget(kDomain1To4);
// Register two callbacks that set the same metric but with different
// label values. The callbacks get used only by plugin1.
gpr_log(GPR_INFO, "testing callbacks for: plugin1");
LOG(INFO) << "testing callbacks for: plugin1";
auto group1 = GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPluginChannelScope(kDomain3To4, ""));
auto callback1 = group1.RegisterCallback(
[&](CallbackMetricReporter& reporter) {
reporter.Report(int64_gauge_handle, 1, kLabelValues,
reporter.Report(int64_gauge_handle, int64_t(1), kLabelValues,
kOptionalLabelValues);
},
{int64_gauge_handle});
Duration::Seconds(5), int64_gauge_handle);
auto callback2 = group1.RegisterCallback(
[&](CallbackMetricReporter& reporter) {
reporter.Report(int64_gauge_handle, 2, kLabelValues2,
reporter.Report(int64_gauge_handle, int64_t(2), kLabelValues2,
kOptionalLabelValues);
},
{int64_gauge_handle});
Duration::Seconds(5), int64_gauge_handle);
// No plugins have data yet.
EXPECT_EQ(plugin1->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_EQ(plugin1->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin1->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_EQ(plugin1->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues2, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin2->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_EQ(plugin2->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin2->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_EQ(plugin2->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues2, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin3->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_EQ(plugin3->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin3->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_EQ(plugin3->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues2, kOptionalLabelValues),
absl::nullopt);
// Now invoke the callbacks.
plugin1->TriggerCallbacks();
plugin2->TriggerCallbacks();
plugin3->TriggerCallbacks();
// Now plugin1 should have data, but the others should not.
EXPECT_THAT(plugin1->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin1->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(1));
EXPECT_THAT(plugin1->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_THAT(plugin1->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues2, kOptionalLabelValues),
::testing::Optional(2));
EXPECT_EQ(plugin2->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_EQ(plugin2->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin2->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_EQ(plugin2->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues2, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin3->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_EQ(plugin3->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin3->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_EQ(plugin3->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues2, kOptionalLabelValues),
absl::nullopt);
// De-register the callbacks.
callback1.reset();
callback2.reset();
// Now register callbacks that hit both plugin1 and plugin2.
gpr_log(GPR_INFO, "testing callbacks for: plugin1, plugin2");
LOG(INFO) << "testing callbacks for: plugin1, plugin2";
auto group2 = GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPluginChannelScope(kDomain2To4, ""));
callback1 = group2.RegisterCallback(
[&](CallbackMetricReporter& reporter) {
reporter.Report(int64_gauge_handle, 3, kLabelValues,
reporter.Report(int64_gauge_handle, int64_t(3), kLabelValues,
kOptionalLabelValues);
},
{int64_gauge_handle});
Duration::Seconds(5), int64_gauge_handle);
callback2 = group2.RegisterCallback(
[&](CallbackMetricReporter& reporter) {
reporter.Report(int64_gauge_handle, 4, kLabelValues2,
reporter.Report(int64_gauge_handle, int64_t(4), kLabelValues2,
kOptionalLabelValues);
},
{int64_gauge_handle});
Duration::Seconds(5), int64_gauge_handle);
// Plugin1 still has data from before, but the others have none.
EXPECT_THAT(plugin1->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin1->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(1));
EXPECT_THAT(plugin1->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_THAT(plugin1->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues2, kOptionalLabelValues),
::testing::Optional(2));
EXPECT_EQ(plugin2->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_EQ(plugin2->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin2->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_EQ(plugin2->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues2, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin3->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_EQ(plugin3->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin3->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_EQ(plugin3->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues2, kOptionalLabelValues),
absl::nullopt);
// Now invoke the callbacks.
plugin1->TriggerCallbacks();
plugin2->TriggerCallbacks();
plugin3->TriggerCallbacks();
// Now plugin1 and plugin2 should have data, but plugin3 should not.
EXPECT_THAT(plugin1->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin1->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(3));
EXPECT_THAT(plugin1->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_THAT(plugin1->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues2, kOptionalLabelValues),
::testing::Optional(4));
EXPECT_THAT(plugin2->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin2->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(3));
EXPECT_THAT(plugin2->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_THAT(plugin2->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues2, kOptionalLabelValues),
::testing::Optional(4));
EXPECT_EQ(plugin3->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_EQ(plugin3->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin3->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_EQ(plugin3->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues2, kOptionalLabelValues),
absl::nullopt);
// De-register the callbacks.
callback1.reset();
callback2.reset();
// Now register callbacks that hit all three plugins.
gpr_log(GPR_INFO, "testing callbacks for: plugin1, plugin2, plugin3");
LOG(INFO) << "testing callbacks for: plugin1, plugin2, plugin3";
auto group3 = GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPluginChannelScope(kDomain1To4, ""));
callback1 = group3.RegisterCallback(
[&](CallbackMetricReporter& reporter) {
reporter.Report(int64_gauge_handle, 5, kLabelValues,
reporter.Report(int64_gauge_handle, int64_t(5), kLabelValues,
kOptionalLabelValues);
},
{int64_gauge_handle});
Duration::Seconds(5), int64_gauge_handle);
callback2 = group3.RegisterCallback(
[&](CallbackMetricReporter& reporter) {
reporter.Report(int64_gauge_handle, 6, kLabelValues2,
reporter.Report(int64_gauge_handle, int64_t(6), kLabelValues2,
kOptionalLabelValues);
},
{int64_gauge_handle});
Duration::Seconds(5), int64_gauge_handle);
// Plugin1 and plugin2 still has data from before, but plugin3 has none.
EXPECT_THAT(plugin1->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin1->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(3));
EXPECT_THAT(plugin1->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_THAT(plugin1->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues2, kOptionalLabelValues),
::testing::Optional(4));
EXPECT_THAT(plugin2->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin2->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(3));
EXPECT_THAT(plugin2->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_THAT(plugin2->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues2, kOptionalLabelValues),
::testing::Optional(4));
EXPECT_EQ(plugin3->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_EQ(plugin3->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin3->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_EQ(plugin3->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues2, kOptionalLabelValues),
absl::nullopt);
// Now invoke the callbacks.
plugin1->TriggerCallbacks();
plugin2->TriggerCallbacks();
plugin3->TriggerCallbacks();
// Now plugin1 and plugin2 should have data, but plugin3 should not.
EXPECT_THAT(plugin1->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin1->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(5));
EXPECT_THAT(plugin1->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_THAT(plugin1->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues2, kOptionalLabelValues),
::testing::Optional(6));
EXPECT_THAT(plugin2->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin2->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(5));
EXPECT_THAT(plugin2->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_THAT(plugin2->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues2, kOptionalLabelValues),
::testing::Optional(6));
EXPECT_THAT(plugin3->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin3->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(5));
EXPECT_THAT(plugin3->GetCallbackGaugeValue(int64_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_THAT(plugin3->GetInt64CallbackGaugeValue(
int64_gauge_handle, kLabelValues2, kOptionalLabelValues),
::testing::Optional(6));
// Need to destroy callbacks before the plugin group that created them.
callback1.reset();
@ -406,18 +403,17 @@ TEST_F(MetricsTest, Int64CallbackGauge) {
}
TEST_F(MetricsTest, DoubleCallbackGauge) {
const absl::string_view kLabelKeys[] = {"label_key_1", "label_key_2"};
const absl::string_view kOptionalLabelKeys[] = {"optional_label_key_1",
"optional_label_key_2"};
auto double_gauge_handle =
GlobalInstrumentsRegistry::RegisterCallbackDoubleGauge(
"double_gauge", "A simple double gauge.", "unit", kLabelKeys,
kOptionalLabelKeys, true);
constexpr absl::string_view kLabelValues[] = {"label_value_1",
"label_value_2"};
constexpr absl::string_view kLabelValues2[] = {"label_value_3",
"label_value_2"};
constexpr absl::string_view kOptionalLabelValues[] = {
"double_gauge", "A simple double gauge.", "unit", true)
.Labels("label_key_1", "label_key_2")
.OptionalLabels("optional_label_key_1", "optional_label_key_2")
.Build();
std::array<absl::string_view, 2> kLabelValues = {"label_value_1",
"label_value_2"};
std::array<absl::string_view, 2> kLabelValues2 = {"label_value_3",
"label_value_2"};
std::array<absl::string_view, 2> kOptionalLabelValues = {
"optional_label_value_1", "optional_label_value_2"};
constexpr absl::string_view kDomain1To4 = "domain1.domain2.domain3.domain4";
constexpr absl::string_view kDomain2To4 = "domain2.domain3.domain4";
@ -427,7 +423,7 @@ TEST_F(MetricsTest, DoubleCallbackGauge) {
auto plugin3 = MakeStatsPluginForTarget(kDomain1To4);
// Register two callbacks that set the same metric but with different
// label values. The callbacks get used only by plugin1.
gpr_log(GPR_INFO, "testing callbacks for: plugin1");
LOG(INFO) << "testing callbacks for: plugin1";
auto group1 = GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPluginChannelScope(kDomain3To4, ""));
auto callback1 = group1.RegisterCallback(
@ -435,60 +431,60 @@ TEST_F(MetricsTest, DoubleCallbackGauge) {
reporter.Report(double_gauge_handle, 1.23, kLabelValues,
kOptionalLabelValues);
},
{double_gauge_handle});
Duration::Seconds(5), double_gauge_handle);
auto callback2 = group1.RegisterCallback(
[&](CallbackMetricReporter& reporter) {
reporter.Report(double_gauge_handle, 2.34, kLabelValues2,
kOptionalLabelValues);
},
{double_gauge_handle});
Duration::Seconds(5), double_gauge_handle);
// No plugins have data yet.
EXPECT_EQ(plugin1->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_EQ(plugin1->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin1->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_EQ(plugin1->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues2, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin2->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_EQ(plugin2->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin2->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_EQ(plugin2->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues2, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin3->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_EQ(plugin3->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin3->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_EQ(plugin3->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues2, kOptionalLabelValues),
absl::nullopt);
// Now invoke the callbacks.
plugin1->TriggerCallbacks();
plugin2->TriggerCallbacks();
plugin3->TriggerCallbacks();
// Now plugin1 should have data, but the others should not.
EXPECT_THAT(plugin1->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin1->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(1.23));
EXPECT_THAT(plugin1->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_THAT(plugin1->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues2, kOptionalLabelValues),
::testing::Optional(2.34));
EXPECT_EQ(plugin2->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_EQ(plugin2->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin2->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_EQ(plugin2->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues2, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin3->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_EQ(plugin3->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin3->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_EQ(plugin3->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues2, kOptionalLabelValues),
absl::nullopt);
// De-register the callbacks.
callback1.reset();
callback2.reset();
// Now register callbacks that hit both plugin1 and plugin2.
gpr_log(GPR_INFO, "testing callbacks for: plugin1, plugin2");
LOG(INFO) << "testing callbacks for: plugin1, plugin2";
auto group2 = GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPluginChannelScope(kDomain2To4, ""));
callback1 = group2.RegisterCallback(
@ -496,60 +492,60 @@ TEST_F(MetricsTest, DoubleCallbackGauge) {
reporter.Report(double_gauge_handle, 3.45, kLabelValues,
kOptionalLabelValues);
},
{double_gauge_handle});
Duration::Seconds(5), double_gauge_handle);
callback2 = group2.RegisterCallback(
[&](CallbackMetricReporter& reporter) {
reporter.Report(double_gauge_handle, 4.56, kLabelValues2,
kOptionalLabelValues);
},
{double_gauge_handle});
Duration::Seconds(5), double_gauge_handle);
// Plugin1 still has data from before, but the others have none.
EXPECT_THAT(plugin1->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin1->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(1.23));
EXPECT_THAT(plugin1->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_THAT(plugin1->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues2, kOptionalLabelValues),
::testing::Optional(2.34));
EXPECT_EQ(plugin2->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_EQ(plugin2->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin2->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_EQ(plugin2->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues2, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin3->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_EQ(plugin3->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin3->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_EQ(plugin3->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues2, kOptionalLabelValues),
absl::nullopt);
// Now invoke the callbacks.
plugin1->TriggerCallbacks();
plugin2->TriggerCallbacks();
plugin3->TriggerCallbacks();
// Now plugin1 and plugin2 should have data, but plugin3 should not.
EXPECT_THAT(plugin1->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin1->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(3.45));
EXPECT_THAT(plugin1->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_THAT(plugin1->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues2, kOptionalLabelValues),
::testing::Optional(4.56));
EXPECT_THAT(plugin2->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin2->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(3.45));
EXPECT_THAT(plugin2->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_THAT(plugin2->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues2, kOptionalLabelValues),
::testing::Optional(4.56));
EXPECT_EQ(plugin3->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_EQ(plugin3->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin3->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_EQ(plugin3->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues2, kOptionalLabelValues),
absl::nullopt);
// De-register the callbacks.
callback1.reset();
callback2.reset();
// Now register callbacks that hit all three plugins.
gpr_log(GPR_INFO, "testing callbacks for: plugin1, plugin2, plugin3");
LOG(INFO) << "testing callbacks for: plugin1, plugin2, plugin3";
auto group3 = GlobalStatsPluginRegistry::GetStatsPluginsForChannel(
StatsPluginChannelScope(kDomain1To4, ""));
callback1 = group3.RegisterCallback(
@ -557,54 +553,54 @@ TEST_F(MetricsTest, DoubleCallbackGauge) {
reporter.Report(double_gauge_handle, 5.67, kLabelValues,
kOptionalLabelValues);
},
{double_gauge_handle});
Duration::Seconds(5), double_gauge_handle);
callback2 = group3.RegisterCallback(
[&](CallbackMetricReporter& reporter) {
reporter.Report(double_gauge_handle, 6.78, kLabelValues2,
kOptionalLabelValues);
},
{double_gauge_handle});
Duration::Seconds(5), double_gauge_handle);
// Plugin1 and plugin2 still has data from before, but plugin3 has none.
EXPECT_THAT(plugin1->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin1->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(3.45));
EXPECT_THAT(plugin1->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_THAT(plugin1->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues2, kOptionalLabelValues),
::testing::Optional(4.56));
EXPECT_THAT(plugin2->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin2->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(3.45));
EXPECT_THAT(plugin2->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_THAT(plugin2->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues2, kOptionalLabelValues),
::testing::Optional(4.56));
EXPECT_EQ(plugin3->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_EQ(plugin3->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues, kOptionalLabelValues),
absl::nullopt);
EXPECT_EQ(plugin3->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_EQ(plugin3->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues2, kOptionalLabelValues),
absl::nullopt);
// Now invoke the callbacks.
plugin1->TriggerCallbacks();
plugin2->TriggerCallbacks();
plugin3->TriggerCallbacks();
// Now plugin1 and plugin2 should have data, but plugin3 should not.
EXPECT_THAT(plugin1->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin1->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(5.67));
EXPECT_THAT(plugin1->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_THAT(plugin1->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues2, kOptionalLabelValues),
::testing::Optional(6.78));
EXPECT_THAT(plugin2->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin2->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(5.67));
EXPECT_THAT(plugin2->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_THAT(plugin2->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues2, kOptionalLabelValues),
::testing::Optional(6.78));
EXPECT_THAT(plugin3->GetCallbackGaugeValue(double_gauge_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_THAT(plugin3->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues, kOptionalLabelValues),
::testing::Optional(5.67));
EXPECT_THAT(plugin3->GetCallbackGaugeValue(double_gauge_handle, kLabelValues2,
kOptionalLabelValues),
EXPECT_THAT(plugin3->GetDoubleCallbackGaugeValue(
double_gauge_handle, kLabelValues2, kOptionalLabelValues),
::testing::Optional(6.78));
// Need to destroy callbacks before the plugin group that created them.
callback1.reset();
@ -612,16 +608,15 @@ TEST_F(MetricsTest, DoubleCallbackGauge) {
}
TEST_F(MetricsTest, DisableByDefaultMetricIsNotRecordedByFakeStatsPlugin) {
const absl::string_view kLabelKeys[] = {"label_key_1", "label_key_2"};
const absl::string_view kOptionalLabelKeys[] = {"optional_label_key_1",
"optional_label_key_2"};
auto double_histogram_handle =
GlobalInstrumentsRegistry::RegisterDoubleHistogram(
"double_histogram", "A simple double histogram.", "unit", kLabelKeys,
kOptionalLabelKeys, /*enable_by_default=*/false);
constexpr absl::string_view kLabelValues[] = {"label_value_1",
"label_value_2"};
constexpr absl::string_view kOptionalLabelValues[] = {
"double_histogram", "A simple double histogram.", "unit", false)
.Labels("label_key_1", "label_key_2")
.OptionalLabels("optional_label_key_1", "optional_label_key_2")
.Build();
std::array<absl::string_view, 2> kLabelValues = {"label_value_1",
"label_value_2"};
std::array<absl::string_view, 2> kOptionalLabelValues = {
"optional_label_value_1", "optional_label_value_2"};
constexpr absl::string_view kDomain1To4 = "domain1.domain2.domain3.domain4";
auto plugin = MakeStatsPluginForTarget(kDomain1To4);
@ -629,24 +624,26 @@ TEST_F(MetricsTest, DisableByDefaultMetricIsNotRecordedByFakeStatsPlugin) {
StatsPluginChannelScope(kDomain1To4, ""))
.RecordHistogram(double_histogram_handle, 1.23, kLabelValues,
kOptionalLabelValues);
EXPECT_EQ(plugin->GetHistogramValue(double_histogram_handle, kLabelValues,
kOptionalLabelValues),
EXPECT_EQ(plugin->GetDoubleHistogramValue(double_histogram_handle,
kLabelValues, kOptionalLabelValues),
absl::nullopt);
}
using MetricsDeathTest = MetricsTest;
TEST_F(MetricsDeathTest, RegisterTheSameMetricNameWouldCrash) {
const absl::string_view kLabelKeys[] = {"label_key_1", "label_key_2"};
const absl::string_view kOptionalLabelKeys[] = {"optional_label_key_1",
"optional_label_key_2"};
(void)GlobalInstrumentsRegistry::RegisterDoubleHistogram(
"double_histogram", "A simple double histogram.", "unit", kLabelKeys,
kOptionalLabelKeys, true);
EXPECT_DEATH(GlobalInstrumentsRegistry::RegisterDoubleHistogram(
"double_histogram", "A simple double histogram.", "unit",
kLabelKeys, kOptionalLabelKeys, true),
"Metric name double_histogram has already been registered.");
"double_histogram", "A simple double histogram.", "unit", true)
.Labels("label_key_1", "label_key_2")
.OptionalLabels("optional_label_key_1", "optional_label_key_2")
.Build();
EXPECT_DEATH(
GlobalInstrumentsRegistry::RegisterDoubleHistogram(
"double_histogram", "A simple double histogram.", "unit", true)
.Labels("label_key_1", "label_key_2")
.OptionalLabels("optional_label_key_1", "optional_label_key_2")
.Build(),
"Metric name double_histogram has already been registered.");
}
} // namespace

@ -26,7 +26,10 @@ licenses(["notice"])
grpc_cc_test(
name = "compression_test",
srcs = ["compression_test.cc"],
external_deps = ["gtest"],
external_deps = [
"absl/log:log",
"gtest",
],
language = "C++",
uses_event_engine = False,
uses_polling = False,
@ -67,7 +70,10 @@ grpc_fuzzer(
grpc_cc_test(
name = "message_compress_test",
srcs = ["message_compress_test.cc"],
external_deps = ["gtest"],
external_deps = [
"absl/log:log",
"gtest",
],
language = "C++",
uses_event_engine = False,
uses_polling = False,

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

Loading…
Cancel
Save