grpc 1.75.0.pre1 → 1.76.0.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (387) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +18 -5
  3. data/include/grpc/credentials.h +21 -5
  4. data/src/core/call/call_filters.cc +4 -4
  5. data/src/core/call/call_filters.h +36 -36
  6. data/src/core/call/call_spine.h +27 -27
  7. data/src/core/call/client_call.cc +6 -5
  8. data/src/core/call/filter_fusion.h +5 -5
  9. data/src/core/call/metadata_batch.h +3 -3
  10. data/src/core/call/security_context.cc +1 -1
  11. data/src/core/call/server_call.cc +4 -4
  12. data/src/core/call/server_call.h +1 -1
  13. data/src/core/channelz/channelz.cc +12 -18
  14. data/src/core/channelz/channelz.h +32 -16
  15. data/src/core/channelz/channelz_registry.h +11 -0
  16. data/src/core/channelz/property_list.cc +18 -0
  17. data/src/core/channelz/property_list.h +10 -1
  18. data/src/core/channelz/text_encode.cc +66 -0
  19. data/src/core/channelz/text_encode.h +29 -0
  20. data/src/core/channelz/v2tov1/convert.cc +11 -0
  21. data/src/core/channelz/v2tov1/legacy_api.cc +15 -8
  22. data/src/core/channelz/ztrace_collector.h +247 -86
  23. data/src/core/client_channel/backup_poller.cc +5 -6
  24. data/src/core/client_channel/client_channel.cc +20 -13
  25. data/src/core/client_channel/client_channel_filter.cc +53 -45
  26. data/src/core/client_channel/client_channel_filter.h +2 -2
  27. data/src/core/client_channel/client_channel_internal.h +3 -4
  28. data/src/core/client_channel/config_selector.h +3 -3
  29. data/src/core/client_channel/dynamic_filters.cc +3 -3
  30. data/src/core/client_channel/global_subchannel_pool.cc +0 -37
  31. data/src/core/client_channel/global_subchannel_pool.h +0 -27
  32. data/src/core/client_channel/load_balanced_call_destination.cc +7 -7
  33. data/src/core/client_channel/local_subchannel_pool.cc +4 -4
  34. data/src/core/client_channel/retry_filter.h +3 -3
  35. data/src/core/client_channel/retry_filter_legacy_call_data.cc +5 -5
  36. data/src/core/client_channel/subchannel.cc +8 -8
  37. data/src/core/client_channel/subchannel_stream_client.cc +4 -4
  38. data/src/core/config/config_vars.cc +30 -1
  39. data/src/core/config/config_vars.h +21 -0
  40. data/src/core/config/core_configuration.cc +5 -5
  41. data/src/core/config/core_configuration.h +7 -7
  42. data/src/core/config/load_config.cc +12 -0
  43. data/src/core/config/load_config.h +2 -0
  44. data/src/core/credentials/call/call_credentials.h +2 -2
  45. data/src/core/credentials/call/call_creds_util.cc +4 -3
  46. data/src/core/credentials/call/composite/composite_call_credentials.cc +4 -4
  47. data/src/core/credentials/call/external/aws_external_account_credentials.cc +3 -3
  48. data/src/core/credentials/call/external/external_account_credentials.cc +1 -1
  49. data/src/core/credentials/call/external/url_external_account_credentials.cc +1 -1
  50. data/src/core/credentials/call/iam/iam_credentials.cc +4 -4
  51. data/src/core/credentials/call/jwt/json_token.cc +3 -3
  52. data/src/core/credentials/call/jwt/jwt_credentials.cc +2 -2
  53. data/src/core/credentials/call/jwt/jwt_verifier.cc +14 -13
  54. data/src/core/credentials/call/oauth2/oauth2_credentials.cc +20 -12
  55. data/src/core/credentials/call/plugin/plugin_credentials.cc +2 -2
  56. data/src/core/credentials/transport/alts/alts_credentials.cc +4 -4
  57. data/src/core/credentials/transport/alts/alts_security_connector.cc +14 -12
  58. data/src/core/credentials/transport/alts/grpc_alts_credentials_client_options.cc +22 -2
  59. data/src/core/credentials/transport/alts/grpc_alts_credentials_options.cc +10 -1
  60. data/src/core/credentials/transport/alts/grpc_alts_credentials_options.h +31 -0
  61. data/src/core/credentials/transport/alts/grpc_alts_credentials_server_options.cc +8 -3
  62. data/src/core/credentials/transport/composite/composite_channel_credentials.cc +5 -5
  63. data/src/core/credentials/transport/fake/fake_security_connector.cc +2 -2
  64. data/src/core/credentials/transport/google_default/google_default_credentials.cc +78 -28
  65. data/src/core/credentials/transport/insecure/insecure_security_connector.cc +3 -3
  66. data/src/core/credentials/transport/local/local_security_connector.cc +8 -8
  67. data/src/core/credentials/transport/security_connector.cc +5 -5
  68. data/src/core/credentials/transport/ssl/ssl_credentials.cc +12 -12
  69. data/src/core/credentials/transport/ssl/ssl_credentials.h +2 -2
  70. data/src/core/credentials/transport/ssl/ssl_security_connector.cc +3 -3
  71. data/src/core/credentials/transport/tls/certificate_provider_registry.cc +2 -2
  72. data/src/core/credentials/transport/tls/grpc_tls_certificate_distributor.cc +24 -24
  73. data/src/core/credentials/transport/tls/grpc_tls_certificate_provider.cc +5 -5
  74. data/src/core/credentials/transport/tls/grpc_tls_certificate_provider.h +2 -2
  75. data/src/core/credentials/transport/tls/grpc_tls_certificate_verifier.cc +2 -2
  76. data/src/core/credentials/transport/tls/grpc_tls_certificate_verifier.h +2 -2
  77. data/src/core/credentials/transport/tls/grpc_tls_credentials_options.cc +17 -17
  78. data/src/core/credentials/transport/tls/ssl_utils.cc +14 -9
  79. data/src/core/credentials/transport/tls/tls_credentials.cc +2 -2
  80. data/src/core/credentials/transport/tls/tls_security_connector.cc +11 -11
  81. data/src/core/credentials/transport/transport_credentials.cc +2 -2
  82. data/src/core/credentials/transport/transport_credentials.h +2 -2
  83. data/src/core/credentials/transport/xds/xds_credentials.cc +5 -5
  84. data/src/core/ext/filters/channel_idle/legacy_channel_idle_filter.cc +2 -0
  85. data/src/core/ext/filters/gcp_authentication/gcp_authentication_filter.cc +1 -1
  86. data/src/core/ext/filters/http/message_compress/compression_filter.cc +8 -8
  87. data/src/core/ext/filters/http/message_compress/compression_filter.h +3 -3
  88. data/src/core/ext/filters/stateful_session/stateful_session_filter.cc +7 -7
  89. data/src/core/ext/transport/chttp2/alpn/alpn.cc +2 -2
  90. data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +10 -9
  91. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +10 -7
  92. data/src/core/ext/transport/chttp2/transport/bin_decoder.cc +5 -5
  93. data/src/core/ext/transport/chttp2/transport/bin_encoder.cc +6 -6
  94. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +96 -88
  95. data/src/core/ext/transport/chttp2/transport/flow_control.cc +3 -3
  96. data/src/core/ext/transport/chttp2/transport/flow_control.h +12 -7
  97. data/src/core/ext/transport/chttp2/transport/flow_control_manager.h +60 -0
  98. data/src/core/ext/transport/chttp2/transport/frame.cc +32 -10
  99. data/src/core/ext/transport/chttp2/transport/frame.h +16 -2
  100. data/src/core/ext/transport/chttp2/transport/frame_data.cc +2 -2
  101. data/src/core/ext/transport/chttp2/transport/frame_goaway.cc +4 -4
  102. data/src/core/ext/transport/chttp2/transport/frame_ping.cc +2 -2
  103. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc +2 -2
  104. data/src/core/ext/transport/chttp2/transport/frame_window_update.cc +3 -3
  105. data/src/core/ext/transport/chttp2/transport/header_assembler.h +28 -12
  106. data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +2 -2
  107. data/src/core/ext/transport/chttp2/transport/hpack_encoder.h +4 -2
  108. data/src/core/ext/transport/chttp2/transport/hpack_encoder_table.cc +8 -8
  109. data/src/core/ext/transport/chttp2/transport/hpack_parse_result.cc +2 -2
  110. data/src/core/ext/transport/chttp2/transport/hpack_parse_result.h +2 -2
  111. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +27 -27
  112. data/src/core/ext/transport/chttp2/transport/hpack_parser.h +2 -3
  113. data/src/core/ext/transport/chttp2/transport/hpack_parser_table.cc +4 -4
  114. data/src/core/ext/transport/chttp2/transport/http2_client_transport.cc +543 -366
  115. data/src/core/ext/transport/chttp2/transport/http2_client_transport.h +198 -277
  116. data/src/core/ext/transport/chttp2/transport/http2_settings_manager.cc +3 -0
  117. data/src/core/ext/transport/chttp2/transport/http2_settings_manager.h +11 -0
  118. data/src/core/ext/transport/chttp2/transport/http2_settings_promises.h +179 -0
  119. data/src/core/ext/transport/chttp2/transport/http2_transport.cc +51 -23
  120. data/src/core/ext/transport/chttp2/transport/http2_transport.h +13 -6
  121. data/src/core/ext/transport/chttp2/transport/http2_ztrace_collector.h +115 -71
  122. data/src/core/ext/transport/chttp2/transport/internal.h +6 -14
  123. data/src/core/ext/transport/chttp2/transport/message_assembler.h +7 -7
  124. data/src/core/ext/transport/chttp2/transport/parsing.cc +17 -15
  125. data/src/core/ext/transport/chttp2/transport/ping_callbacks.cc +2 -2
  126. data/src/core/ext/transport/chttp2/transport/ping_promise.cc +62 -26
  127. data/src/core/ext/transport/chttp2/transport/ping_promise.h +58 -22
  128. data/src/core/ext/transport/chttp2/transport/stream.h +207 -0
  129. data/src/core/ext/transport/chttp2/transport/stream_data_queue.h +328 -187
  130. data/src/core/ext/transport/chttp2/transport/stream_lists.cc +7 -7
  131. data/src/core/ext/transport/chttp2/transport/transport_common.cc +17 -1
  132. data/src/core/ext/transport/chttp2/transport/transport_common.h +52 -0
  133. data/src/core/ext/transport/chttp2/transport/varint.h +2 -2
  134. data/src/core/ext/transport/chttp2/transport/writable_streams.h +181 -79
  135. data/src/core/ext/transport/chttp2/transport/write_size_policy.cc +2 -2
  136. data/src/core/ext/transport/chttp2/transport/writing.cc +3 -3
  137. data/src/core/ext/transport/inproc/inproc_transport.cc +1 -1
  138. data/src/core/ext/transport/inproc/legacy_inproc_transport.cc +3 -3
  139. data/src/core/ext/upb-gen/src/proto/grpc/channelz/v2/service.upb.h +740 -0
  140. data/src/core/ext/upb-gen/src/proto/grpc/channelz/v2/service.upb_minitable.c +218 -0
  141. data/src/core/ext/upb-gen/src/proto/grpc/channelz/v2/service.upb_minitable.h +46 -0
  142. data/src/core/ext/upb-gen/src/proto/grpc/gcp/handshaker.upb.h +87 -55
  143. data/src/core/ext/upb-gen/src/proto/grpc/gcp/handshaker.upb_minitable.c +23 -21
  144. data/src/core/ext/upbdefs-gen/src/proto/grpc/channelz/v2/channelz.upbdefs.c +80 -0
  145. data/src/core/ext/upbdefs-gen/src/proto/grpc/channelz/v2/channelz.upbdefs.h +47 -0
  146. data/src/core/ext/upbdefs-gen/src/proto/grpc/channelz/v2/service.upbdefs.c +129 -0
  147. data/src/core/ext/upbdefs-gen/src/proto/grpc/channelz/v2/service.upbdefs.h +72 -0
  148. data/src/core/filter/auth/server_auth_filter.cc +2 -2
  149. data/src/core/handshaker/handshaker.cc +3 -3
  150. data/src/core/handshaker/http_connect/http_proxy_mapper.cc +2 -2
  151. data/src/core/handshaker/security/legacy_secure_endpoint.cc +2 -2
  152. data/src/core/handshaker/security/pipelined_secure_endpoint.cc +31 -8
  153. data/src/core/handshaker/security/secure_endpoint.cc +16 -6
  154. data/src/core/handshaker/security/security_handshaker.cc +3 -3
  155. data/src/core/handshaker/tcp_connect/tcp_connect_handshaker.cc +2 -2
  156. data/src/core/lib/channel/channel_stack.cc +8 -5
  157. data/src/core/lib/channel/channel_stack.h +3 -0
  158. data/src/core/lib/channel/channel_stack_builder_impl.cc +1 -0
  159. data/src/core/lib/channel/connected_channel.cc +2 -2
  160. data/src/core/lib/channel/promise_based_filter.cc +69 -64
  161. data/src/core/lib/channel/promise_based_filter.h +16 -15
  162. data/src/core/lib/compression/compression_internal.cc +2 -2
  163. data/src/core/lib/compression/message_compress.cc +7 -7
  164. data/src/core/lib/event_engine/ares_resolver.cc +22 -20
  165. data/src/core/lib/event_engine/cf_engine/cf_engine.cc +2 -2
  166. data/src/core/lib/event_engine/cf_engine/dns_service_resolver.cc +2 -2
  167. data/src/core/lib/event_engine/cf_engine/dns_service_resolver.h +2 -2
  168. data/src/core/lib/event_engine/extensions/channelz.h +2 -2
  169. data/src/core/lib/event_engine/extensions/supports_fd.h +5 -5
  170. data/src/core/lib/event_engine/posix_engine/ev_epoll1_linux.cc +8 -8
  171. data/src/core/lib/event_engine/posix_engine/ev_poll_posix.cc +10 -10
  172. data/src/core/lib/event_engine/posix_engine/lockfree_event.cc +2 -2
  173. data/src/core/lib/event_engine/posix_engine/posix_endpoint.cc +23 -22
  174. data/src/core/lib/event_engine/posix_engine/posix_endpoint.h +11 -11
  175. data/src/core/lib/event_engine/posix_engine/posix_engine.cc +168 -170
  176. data/src/core/lib/event_engine/posix_engine/posix_engine.h +33 -54
  177. data/src/core/lib/event_engine/posix_engine/posix_engine_listener.cc +4 -3
  178. data/src/core/lib/event_engine/posix_engine/posix_engine_listener_utils.cc +5 -5
  179. data/src/core/lib/event_engine/posix_engine/posix_interface.h +1 -1
  180. data/src/core/lib/event_engine/posix_engine/tcp_socket_utils.cc +1 -1
  181. data/src/core/lib/event_engine/posix_engine/timer_manager.cc +3 -3
  182. data/src/core/lib/event_engine/resolved_address.cc +3 -3
  183. data/src/core/lib/event_engine/shim.cc +8 -11
  184. data/src/core/lib/event_engine/shim.h +2 -1
  185. data/src/core/lib/event_engine/slice.cc +2 -2
  186. data/src/core/lib/event_engine/tcp_socket_utils.cc +11 -11
  187. data/src/core/lib/event_engine/thread_pool/work_stealing_thread_pool.cc +7 -7
  188. data/src/core/lib/event_engine/windows/grpc_polled_fd_windows.cc +31 -31
  189. data/src/core/lib/event_engine/windows/iocp.cc +10 -10
  190. data/src/core/lib/event_engine/windows/win_socket.cc +6 -6
  191. data/src/core/lib/event_engine/windows/windows_endpoint.cc +11 -11
  192. data/src/core/lib/event_engine/windows/windows_engine.cc +16 -14
  193. data/src/core/lib/event_engine/windows/windows_listener.cc +7 -7
  194. data/src/core/lib/experiments/experiments.cc +105 -18
  195. data/src/core/lib/experiments/experiments.h +43 -11
  196. data/src/core/lib/iomgr/call_combiner.cc +3 -3
  197. data/src/core/lib/iomgr/endpoint_cfstream.cc +6 -6
  198. data/src/core/lib/iomgr/endpoint_pair_posix.cc +5 -5
  199. data/src/core/lib/iomgr/endpoint_pair_windows.cc +15 -14
  200. data/src/core/lib/iomgr/ev_epoll1_linux.cc +15 -15
  201. data/src/core/lib/iomgr/ev_poll_posix.cc +11 -11
  202. data/src/core/lib/iomgr/event_engine_shims/endpoint.cc +5 -4
  203. data/src/core/lib/iomgr/event_engine_shims/endpoint.h +1 -1
  204. data/src/core/lib/iomgr/iocp_windows.cc +8 -8
  205. data/src/core/lib/iomgr/iomgr_windows.cc +3 -3
  206. data/src/core/lib/iomgr/lockfree_event.cc +2 -2
  207. data/src/core/lib/iomgr/polling_entity.cc +3 -3
  208. data/src/core/lib/iomgr/socket_utils_common_posix.cc +2 -2
  209. data/src/core/lib/iomgr/socket_windows.cc +4 -4
  210. data/src/core/lib/iomgr/tcp_client_posix.cc +4 -4
  211. data/src/core/lib/iomgr/tcp_client_windows.cc +4 -4
  212. data/src/core/lib/iomgr/tcp_posix.cc +42 -42
  213. data/src/core/lib/iomgr/tcp_server.cc +5 -0
  214. data/src/core/lib/iomgr/tcp_server.h +7 -0
  215. data/src/core/lib/iomgr/tcp_server_posix.cc +47 -27
  216. data/src/core/lib/iomgr/tcp_server_utils_posix.h +3 -0
  217. data/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +5 -5
  218. data/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc +2 -2
  219. data/src/core/lib/iomgr/tcp_server_windows.cc +68 -29
  220. data/src/core/lib/iomgr/tcp_windows.cc +7 -7
  221. data/src/core/lib/iomgr/timer_generic.cc +2 -2
  222. data/src/core/lib/iomgr/timer_manager.cc +2 -2
  223. data/src/core/lib/iomgr/unix_sockets_posix.cc +2 -2
  224. data/src/core/lib/iomgr/unix_sockets_posix_noop.cc +2 -2
  225. data/src/core/lib/promise/activity.cc +2 -2
  226. data/src/core/lib/promise/activity.h +6 -6
  227. data/src/core/lib/promise/context.h +2 -2
  228. data/src/core/lib/promise/detail/join_state.h +9 -9
  229. data/src/core/lib/promise/detail/seq_state.h +13 -13
  230. data/src/core/lib/promise/detail/status.h +2 -2
  231. data/src/core/lib/promise/for_each.h +5 -5
  232. data/src/core/lib/promise/interceptor_list.h +2 -2
  233. data/src/core/lib/promise/latch.h +7 -7
  234. data/src/core/lib/promise/mpsc.cc +26 -26
  235. data/src/core/lib/promise/mpsc.h +2 -2
  236. data/src/core/lib/promise/observable.h +4 -4
  237. data/src/core/lib/promise/party.cc +32 -25
  238. data/src/core/lib/promise/party.h +16 -19
  239. data/src/core/lib/promise/pipe.h +15 -15
  240. data/src/core/lib/promise/poll.h +5 -4
  241. data/src/core/lib/promise/promise.h +0 -2
  242. data/src/core/lib/promise/sleep.cc +3 -1
  243. data/src/core/lib/promise/status_flag.h +7 -7
  244. data/src/core/lib/promise/try_join.h +2 -2
  245. data/src/core/lib/promise/try_seq.h +2 -2
  246. data/src/core/lib/resource_quota/arena.h +15 -2
  247. data/src/core/lib/resource_quota/connection_quota.cc +9 -7
  248. data/src/core/lib/resource_quota/memory_quota.cc +45 -24
  249. data/src/core/lib/resource_quota/memory_quota.h +48 -16
  250. data/src/core/lib/resource_quota/telemetry.h +54 -0
  251. data/src/core/lib/resource_quota/thread_quota.cc +2 -2
  252. data/src/core/lib/resource_tracker/resource_tracker.cc +33 -0
  253. data/src/core/lib/resource_tracker/resource_tracker.h +46 -0
  254. data/src/core/lib/security/authorization/audit_logging.cc +5 -5
  255. data/src/core/lib/security/authorization/grpc_authorization_engine.cc +2 -2
  256. data/src/core/lib/security/authorization/stdout_logger.cc +3 -3
  257. data/src/core/lib/surface/byte_buffer_reader.cc +2 -2
  258. data/src/core/lib/surface/call.cc +16 -14
  259. data/src/core/lib/surface/call.h +1 -1
  260. data/src/core/lib/surface/call_utils.cc +2 -2
  261. data/src/core/lib/surface/call_utils.h +2 -2
  262. data/src/core/lib/surface/channel.cc +4 -4
  263. data/src/core/lib/surface/channel_create.cc +10 -6
  264. data/src/core/lib/surface/channel_init.cc +80 -23
  265. data/src/core/lib/surface/channel_init.h +26 -11
  266. data/src/core/lib/surface/completion_queue.cc +17 -16
  267. data/src/core/lib/surface/completion_queue_factory.cc +7 -7
  268. data/src/core/lib/surface/connection_context.h +45 -2
  269. data/src/core/lib/surface/filter_stack_call.cc +12 -23
  270. data/src/core/lib/surface/filter_stack_call.h +3 -4
  271. data/src/core/lib/surface/legacy_channel.cc +7 -7
  272. data/src/core/lib/surface/validate_metadata.h +2 -2
  273. data/src/core/lib/surface/version.cc +2 -2
  274. data/src/core/lib/transport/bdp_estimator.cc +2 -2
  275. data/src/core/lib/transport/bdp_estimator.h +3 -3
  276. data/src/core/lib/transport/promise_endpoint.cc +3 -3
  277. data/src/core/lib/transport/promise_endpoint.h +8 -8
  278. data/src/core/lib/transport/timeout_encoding.cc +4 -4
  279. data/src/core/load_balancing/child_policy_handler.cc +4 -4
  280. data/src/core/load_balancing/endpoint_list.cc +2 -2
  281. data/src/core/load_balancing/grpclb/grpclb.cc +24 -24
  282. data/src/core/load_balancing/health_check_client.cc +4 -4
  283. data/src/core/load_balancing/health_check_client_internal.h +2 -2
  284. data/src/core/load_balancing/lb_policy_registry.cc +2 -2
  285. data/src/core/load_balancing/oob_backend_metric.cc +4 -4
  286. data/src/core/load_balancing/oob_backend_metric_internal.h +2 -2
  287. data/src/core/load_balancing/outlier_detection/outlier_detection.cc +2 -2
  288. data/src/core/load_balancing/pick_first/pick_first.cc +14 -14
  289. data/src/core/load_balancing/priority/priority.cc +23 -24
  290. data/src/core/load_balancing/ring_hash/ring_hash.cc +3 -3
  291. data/src/core/load_balancing/rls/rls.cc +13 -13
  292. data/src/core/load_balancing/round_robin/round_robin.cc +9 -9
  293. data/src/core/load_balancing/weighted_round_robin/static_stride_scheduler.cc +3 -3
  294. data/src/core/load_balancing/weighted_round_robin/weighted_round_robin.cc +33 -26
  295. data/src/core/load_balancing/weighted_target/weighted_target.cc +5 -5
  296. data/src/core/load_balancing/xds/cds.cc +76 -32
  297. data/src/core/load_balancing/xds/xds_cluster_impl.cc +3 -3
  298. data/src/core/load_balancing/xds/xds_override_host.cc +4 -4
  299. data/src/core/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc +2 -2
  300. data/src/core/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +33 -33
  301. data/src/core/resolver/dns/c_ares/grpc_ares_wrapper.cc +10 -10
  302. data/src/core/resolver/dns/dns_resolver_plugin.cc +6 -3
  303. data/src/core/resolver/dns/event_engine/event_engine_client_channel_resolver.cc +2 -2
  304. data/src/core/resolver/endpoint_addresses.cc +3 -3
  305. data/src/core/resolver/endpoint_addresses.h +3 -0
  306. data/src/core/resolver/fake/fake_resolver.cc +2 -2
  307. data/src/core/resolver/google_c2p/google_c2p_resolver.cc +41 -54
  308. data/src/core/resolver/polling_resolver.cc +3 -3
  309. data/src/core/resolver/resolver_registry.cc +5 -4
  310. data/src/core/resolver/xds/xds_dependency_manager.cc +5 -5
  311. data/src/core/resolver/xds/xds_resolver.cc +9 -9
  312. data/src/core/server/server.cc +38 -38
  313. data/src/core/server/server_call_tracer_filter.h +4 -4
  314. data/src/core/server/server_config_selector_filter.cc +2 -2
  315. data/src/core/server/xds_server_config_fetcher.cc +9 -8
  316. data/src/core/service_config/service_config_impl.h +2 -2
  317. data/src/core/telemetry/call_tracer.cc +39 -49
  318. data/src/core/telemetry/call_tracer.h +199 -22
  319. data/src/core/telemetry/histogram.h +205 -0
  320. data/src/core/telemetry/instrument.cc +719 -0
  321. data/src/core/telemetry/instrument.h +932 -0
  322. data/src/core/telemetry/metrics.cc +13 -5
  323. data/src/core/telemetry/metrics.h +3 -1
  324. data/src/core/telemetry/stats_data.cc +0 -19
  325. data/src/core/telemetry/stats_data.h +0 -19
  326. data/src/core/transport/auth_context.cc +2 -2
  327. data/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +78 -45
  328. data/src/core/tsi/alts/handshaker/alts_handshaker_client.h +1 -0
  329. data/src/core/tsi/alts/handshaker/alts_shared_resource.cc +3 -3
  330. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +39 -31
  331. data/src/core/tsi/alts/handshaker/alts_tsi_utils.cc +3 -3
  332. data/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.cc +3 -3
  333. data/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.cc +7 -7
  334. data/src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc +3 -3
  335. data/src/core/tsi/fake_transport_security.cc +4 -4
  336. data/src/core/tsi/ssl/key_logging/ssl_key_logging.cc +4 -4
  337. data/src/core/tsi/ssl/session_cache/ssl_session_cache.cc +9 -9
  338. data/src/core/tsi/ssl/session_cache/ssl_session_openssl.cc +3 -3
  339. data/src/core/tsi/ssl_transport_security.cc +26 -25
  340. data/src/core/tsi/ssl_transport_security_utils.cc +9 -9
  341. data/src/core/util/chunked_vector.h +4 -4
  342. data/src/core/util/event_log.cc +2 -2
  343. data/src/core/util/gcp_metadata_query.cc +2 -2
  344. data/src/core/util/grpc_check.cc +22 -0
  345. data/src/core/util/grpc_check.h +103 -0
  346. data/src/core/util/http_client/httpcli.cc +3 -3
  347. data/src/core/util/http_client/parser.cc +4 -4
  348. data/src/core/util/latent_see.h +7 -4
  349. data/src/core/util/lru_cache.h +4 -4
  350. data/src/core/util/memory_usage.h +16 -0
  351. data/src/core/util/posix/directory_reader.cc +3 -2
  352. data/src/core/util/posix/sync.cc +24 -24
  353. data/src/core/util/postmortem_emit.cc +52 -0
  354. data/src/core/util/postmortem_emit.h +30 -0
  355. data/src/core/util/ref_counted_ptr.h +5 -0
  356. data/src/core/util/trie_lookup.h +170 -0
  357. data/src/core/util/unique_ptr_with_bitset.h +5 -5
  358. data/src/core/xds/grpc/xds_bootstrap_grpc.h +6 -1
  359. data/src/core/xds/grpc/xds_certificate_provider.cc +3 -3
  360. data/src/core/xds/grpc/xds_client_grpc.cc +34 -15
  361. data/src/core/xds/grpc/xds_client_grpc.h +4 -1
  362. data/src/core/xds/grpc/xds_cluster_parser.cc +2 -2
  363. data/src/core/xds/grpc/xds_cluster_specifier_plugin.cc +2 -2
  364. data/src/core/xds/grpc/xds_endpoint_parser.cc +2 -2
  365. data/src/core/xds/grpc/xds_http_filter_registry.cc +4 -3
  366. data/src/core/xds/grpc/xds_listener_parser.cc +3 -3
  367. data/src/core/xds/grpc/xds_matcher.cc +277 -0
  368. data/src/core/xds/grpc/xds_matcher.h +432 -0
  369. data/src/core/xds/grpc/xds_matcher_action.cc +47 -0
  370. data/src/core/xds/grpc/xds_matcher_action.h +48 -0
  371. data/src/core/xds/grpc/xds_matcher_context.cc +29 -0
  372. data/src/core/xds/grpc/xds_matcher_context.h +46 -0
  373. data/src/core/xds/grpc/xds_matcher_input.cc +79 -0
  374. data/src/core/xds/grpc/xds_matcher_input.h +105 -0
  375. data/src/core/xds/grpc/xds_matcher_parse.cc +356 -0
  376. data/src/core/xds/grpc/xds_matcher_parse.h +39 -0
  377. data/src/core/xds/grpc/xds_metadata.cc +4 -3
  378. data/src/core/xds/grpc/xds_route_config_parser.cc +6 -6
  379. data/src/core/xds/grpc/xds_routing.cc +3 -3
  380. data/src/core/xds/grpc/xds_transport_grpc.cc +10 -10
  381. data/src/core/xds/xds_client/lrs_client.cc +6 -6
  382. data/src/core/xds/xds_client/xds_client.cc +9 -9
  383. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +2 -2
  384. data/src/ruby/lib/grpc/version.rb +1 -1
  385. data/third_party/abseil-cpp/absl/container/internal/node_slot_policy.h +95 -0
  386. data/third_party/abseil-cpp/absl/container/node_hash_map.h +687 -0
  387. metadata +37 -2
@@ -0,0 +1,932 @@
1
+ // Copyright 2025 gRPC authors.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ // This file defines the core interfaces for gRPC telemetry instrumentation.
16
+ //
17
+ // ## Concepts
18
+ //
19
+ // * **Instrument:** An individual metric being tracked. This can be a
20
+ // counter, gauge, histogram, etc. Each instrument has a unique name,
21
+ // description, and unit.
22
+ //
23
+ // * **Instrument Domain:** A collection of instruments that share a common
24
+ // set of labels. For example, all metrics related to a specific resource
25
+ // quota might belong to the same domain. Domains are defined by inheriting
26
+ // from `InstrumentDomain` and specifying the labels and backend type.
27
+ //
28
+ // * **Labels:** Key-value pairs that provide dimensions to metrics. Each
29
+ // unique combination of label values within a domain creates a separate
30
+ // instance of the instrumentation storage.
31
+ //
32
+ // * **Storage:** An object holding the current values for all instruments
33
+ // within a domain, for a *specific combination* of label values. Storage
34
+ // objects are ref-counted and managed by the domain. You obtain a
35
+ // `RefCountedPtr<Storage>` using `Domain::GetStorage(...)`, passing the
36
+ // current label values.
37
+ //
38
+ // * **Backend:** Determines how the metric data is stored and aggregated
39
+ // within a Storage object. Examples include `LowContentionBackend` and
40
+ // `HighContentionBackend` for counters and histograms.
41
+ //
42
+ // ## Instrument Types
43
+ //
44
+ // * **Counter:** A metric that only increases. Uses `RegisterCounter` and
45
+ // `Storage::Increment`.
46
+ // * **Histogram:** Tracks the distribution of values. Uses
47
+ // `RegisterHistogram` and `Storage::Increment`.
48
+ // * **Gauges:** Metrics that can go up or down, representing a current value.
49
+ // * `DoubleGauge`: for double values.
50
+ // * `IntGauge`: for int64_t values.
51
+ // * `UintGauge`: for uint64_t values.
52
+ // Gauges are registered using `RegisterDoubleGauge`, `RegisterIntGauge`, or
53
+ // `RegisterUintGauge`.
54
+ //
55
+ // ## Gauge Providers
56
+ //
57
+ // Unlike counters and histograms, gauge values are not stored directly in the
58
+ // `Backend`. Instead, they are derived from the current state of an object.
59
+ // Objects that need to expose gauge metrics should implement the
60
+ // `GaugeProvider<Domain>` interface. They register/unregister via methods on
61
+ // the base class.
62
+ //
63
+ // Example:
64
+ // // In your class that has the gauge data:
65
+ // class MyProvider : public GaugeProvider<MyDomain> {
66
+ // public:
67
+ // MyProvider(InstrumentStorageRefPtr<MyDomain> storage)
68
+ // : GaugeProvider<MyDomain>(std::move(storage)) {
69
+ // ProviderConstructed();
70
+ // }
71
+ // ~MyProvider() override { ProviderDestructing(); }
72
+ //
73
+ // void PopulateGaugeData(GaugeSink<MyDomain>& sink) override {
74
+ // sink.Set(MyDomain::kMyGauge, GetCurrentValue());
75
+ // }
76
+ // };
77
+ //
78
+ // ## Declaring an Instrument Domain
79
+ //
80
+ // To define a new set of metrics, you create a class that inherits from
81
+ // `InstrumentDomain<YourDomainName>`. This class must define:
82
+ //
83
+ // 1. `using Backend = ...;`: Specifies the backend type (e.g.,
84
+ // `LowContentionBackend`, `HighContentionBackend`).
85
+ // 2. `static constexpr auto kLabels = std::tuple(...);`: Defines the names
86
+ // of the labels for this domain. The types of the labels are inferred
87
+ // from the arguments passed to `GetStorage()`.
88
+ //
89
+ // Instruments are registered as static members within the domain class using
90
+ // the `Register*` methods.
91
+ //
92
+ // Example:
93
+ // class MyDomain : public InstrumentDomain<MyDomain> {
94
+ // public:
95
+ // using Backend = LowContentionBackend;
96
+ // static constexpr auto kLabels = std::tuple("my_label", "another_label");
97
+ //
98
+ // // Register a counter:
99
+ // static inline const auto kMyCounter = RegisterCounter(
100
+ // "grpc.my_domain.my_counter", "Description of my counter", "units");
101
+ //
102
+ // // Register a gauge:
103
+ // static inline const auto kMyGauge = RegisterIntGauge(
104
+ // "grpc.my_domain.my_gauge", "Description of my gauge", "units");
105
+ // };
106
+ //
107
+ // To increment the counter:
108
+ // auto storage = MyDomain::GetStorage("label_val1", "label_val2");
109
+ // storage->Increment(MyDomain::kMyCounter);
110
+ //
111
+ // To set the gauge (inside a callback):
112
+ // sink.Set(MyDomain::kMyGauge, current_gauge_value);
113
+ //
114
+ // ## Querying Metrics
115
+ //
116
+ // The `MetricsQuery` class is used to fetch metric data. You can filter by
117
+ // label values, select specific metrics, and collapse labels (aggregate over
118
+ // them). The results are emitted to a `MetricsSink` interface.
119
+ //
120
+ // ## Aggregability
121
+ //
122
+ // * **Counters & Histograms:** Are aggregatable. When labels are collapsed
123
+ // using `MetricsQuery::CollapseLabels`, values from different label
124
+ // combinations are summed up.
125
+ // * **Gauges:** Are NOT aggregatable. Collapsing labels on a query that
126
+ // includes gauges is not meaningful, as summing up current values from
127
+ // different sources makes no sense. The `MetricsSink` will receive
128
+ // individual gauge readings for each label set matching the filter.
129
+
130
+ #ifndef GRPC_SRC_CORE_TELEMETRY_INSTRUMENT_H
131
+ #define GRPC_SRC_CORE_TELEMETRY_INSTRUMENT_H
132
+
133
+ #include <grpc/support/cpu.h>
134
+ #include <grpc/support/port_platform.h>
135
+
136
+ #include <algorithm>
137
+ #include <array>
138
+ #include <atomic>
139
+ #include <cstdint>
140
+ #include <memory>
141
+ #include <optional>
142
+ #include <string>
143
+ #include <tuple>
144
+ #include <utility>
145
+ #include <variant>
146
+ #include <vector>
147
+
148
+ #include "absl/base/thread_annotations.h"
149
+ #include "absl/container/flat_hash_map.h"
150
+ #include "absl/container/flat_hash_set.h"
151
+ #include "absl/container/node_hash_map.h"
152
+ #include "absl/log/log.h"
153
+ #include "absl/strings/str_cat.h"
154
+ #include "absl/strings/string_view.h"
155
+ #include "absl/types/span.h"
156
+ #include "src/core/telemetry/histogram.h"
157
+ #include "src/core/util/avl.h"
158
+ #include "src/core/util/dual_ref_counted.h"
159
+ #include "src/core/util/match.h"
160
+ #include "src/core/util/per_cpu.h"
161
+ #include "src/core/util/ref_counted_ptr.h"
162
+ #include "src/core/util/sync.h"
163
+
164
+ namespace grpc_core {
165
+
166
+ class InstrumentTest;
167
+
168
+ namespace instrument_detail {
169
+ class QueryableDomain;
170
+ class StorageSet;
171
+ } // namespace instrument_detail
172
+
173
+ class CollectionScope;
174
+
175
+ class InstrumentMetadata {
176
+ public:
177
+ struct CounterShape {};
178
+ struct DoubleGaugeShape {};
179
+ struct IntGaugeShape {};
180
+ struct UintGaugeShape {};
181
+ using HistogramShape = HistogramBuckets;
182
+
183
+ using Shape = std::variant<CounterShape, HistogramShape, DoubleGaugeShape,
184
+ IntGaugeShape, UintGaugeShape>;
185
+
186
+ // A description of a metric.
187
+ struct Description {
188
+ // The domain that owns the metric.
189
+ instrument_detail::QueryableDomain* domain;
190
+ // The offset of the metric within the domain's allocated metrics.
191
+ uint64_t offset;
192
+ // The name of the metric.
193
+ absl::string_view name;
194
+ // A description of the metric.
195
+ absl::string_view description;
196
+ // The unit of the metric.
197
+ absl::string_view unit;
198
+ // The shape of the metric - for counters this is empty.
199
+ // For histograms, it defines the buckets.
200
+ Shape shape;
201
+ };
202
+
203
+ // Iterate all metric descriptions in all domains.
204
+ static void ForEachInstrument(absl::FunctionRef<void(const Description*)> fn);
205
+ };
206
+
207
+ class MetricsQuery;
208
+ class MetricsSink;
209
+
210
+ // OpenTelemetry has no facility to export histogram data in the API (though
211
+ // there is a facility in the SDK). To cover this gap, if we are accessed via
212
+ // the OpenTelemetry API without the SDK being known to gRPC, we register a hook
213
+ // to be called when histogram data is collected.
214
+ // This comes with a relatively sever performance penalty. We'd like to be able
215
+ // to remove this in the future.
216
+ using HistogramCollectionHook = absl::AnyInvocable<void(
217
+ const InstrumentMetadata::Description* instrument,
218
+ absl::Span<const std::string> labels, int64_t value)>;
219
+ void RegisterHistogramCollectionHook(HistogramCollectionHook hook);
220
+
221
+ // A CollectionScope ensures that all metric updates in its lifetime are visible
222
+ // to a MetricsQuery.
223
+ class CollectionScope {
224
+ public:
225
+ explicit CollectionScope(
226
+ std::vector<std::unique_ptr<instrument_detail::StorageSet>> storage_sets);
227
+
228
+ size_t TestOnlyCountStorageHeld() const;
229
+
230
+ private:
231
+ friend class MetricsQuery;
232
+ std::vector<instrument_detail::StorageSet*> GetStorageSets();
233
+
234
+ std::vector<std::unique_ptr<instrument_detail::StorageSet>> storage_sets_;
235
+ };
236
+
237
+ namespace instrument_detail {
238
+
239
+ void CallHistogramCollectionHooks(
240
+ const InstrumentMetadata::Description* instrument,
241
+ absl::Span<const std::string> labels, int64_t value);
242
+
243
+ class GaugeStorage {
244
+ public:
245
+ explicit GaugeStorage(QueryableDomain* domain);
246
+
247
+ void SetDouble(uint64_t offset, double value) {
248
+ DCHECK_LT(offset, double_gauges_.size());
249
+ double_gauges_[offset] = value;
250
+ }
251
+ void SetInt(uint64_t offset, int64_t value) {
252
+ DCHECK_LT(offset, int_gauges_.size());
253
+ int_gauges_[offset] = value;
254
+ }
255
+ void SetUint(uint64_t offset, uint64_t value) {
256
+ DCHECK_LT(offset, uint_gauges_.size());
257
+ uint_gauges_[offset] = value;
258
+ }
259
+
260
+ std::optional<double> GetDouble(uint64_t offset) const {
261
+ DCHECK_LT(offset, double_gauges_.size());
262
+ return double_gauges_[offset];
263
+ }
264
+ std::optional<int64_t> GetInt(uint64_t offset) const {
265
+ DCHECK_LT(offset, int_gauges_.size());
266
+ return int_gauges_[offset];
267
+ }
268
+ std::optional<uint64_t> GetUint(uint64_t offset) const {
269
+ DCHECK_LT(offset, uint_gauges_.size());
270
+ return uint_gauges_[offset];
271
+ }
272
+
273
+ private:
274
+ std::vector<std::optional<double>> double_gauges_;
275
+ std::vector<std::optional<int64_t>> int_gauges_;
276
+ std::vector<std::optional<uint64_t>> uint_gauges_;
277
+ };
278
+
279
+ class DomainStorage : public DualRefCounted<DomainStorage> {
280
+ public:
281
+ DomainStorage(QueryableDomain* domain, std::vector<std::string> label);
282
+
283
+ void Orphaned() override;
284
+
285
+ virtual uint64_t SumCounter(size_t index) = 0;
286
+
287
+ absl::Span<const std::string> label() const { return label_; }
288
+ QueryableDomain* domain() const { return domain_; }
289
+
290
+ virtual void FillGaugeStorage(GaugeStorage& gauge_storage) = 0;
291
+
292
+ private:
293
+ QueryableDomain* domain_;
294
+ const std::vector<std::string> label_;
295
+ };
296
+
297
+ // Interface for a set of storage objects for a domain.
298
+ // Each StorageSet is a collection of storage objects for a domain, one storage
299
+ // object per unique set of labels.
300
+ // The StorageSet subscribes to new label sets being created, so that all
301
+ // storage in a time period can be exported.
302
+ class StorageSet {
303
+ public:
304
+ StorageSet(QueryableDomain* domain, size_t map_shards_size);
305
+ virtual ~StorageSet();
306
+ void ExportMetrics(
307
+ MetricsSink& sink,
308
+ absl::Span<const InstrumentMetadata::Description* const> metrics);
309
+ size_t TestOnlyCountStorageHeld() const;
310
+ QueryableDomain* domain() const { return domain_; }
311
+
312
+ void AddStorage(WeakRefCountedPtr<DomainStorage> storage);
313
+
314
+ private:
315
+ struct MapShard {
316
+ mutable Mutex mu;
317
+ AVL<absl::Span<const std::string>, WeakRefCountedPtr<DomainStorage>>
318
+ storage_map ABSL_GUARDED_BY(mu);
319
+ };
320
+
321
+ QueryableDomain* domain_;
322
+ std::unique_ptr<MapShard[]> map_shards_;
323
+ const size_t map_shards_size_;
324
+ };
325
+
326
+ // A registry of metrics.
327
+ // In this singleton we maintain metadata about all registered metrics.
328
+ class InstrumentIndex {
329
+ public:
330
+ // Returns the singleton instance of the InstrumentIndex.
331
+ static InstrumentIndex& Get() {
332
+ static InstrumentIndex* index = new InstrumentIndex();
333
+ return *index;
334
+ }
335
+
336
+ // Registers a metric with the given name, description, unit, and shape.
337
+ // Returns a pointer to the Description struct, which contains metadata about
338
+ // the metric.
339
+ const InstrumentMetadata::Description* Register(
340
+ QueryableDomain* domain, uint64_t offset, absl::string_view name,
341
+ absl::string_view description, absl::string_view unit,
342
+ InstrumentMetadata::Shape shape);
343
+
344
+ // Finds a metric with the given name, or nullptr if not found.
345
+ const InstrumentMetadata::Description* Find(absl::string_view name) const;
346
+
347
+ private:
348
+ InstrumentIndex() = default;
349
+
350
+ // A map of metric name to Description. We use node_hash_map because we need
351
+ // pointer stability for the values.
352
+ absl::node_hash_map<absl::string_view, InstrumentMetadata::Description>
353
+ metrics_;
354
+ };
355
+
356
+ // A QueryableDomain is a collection of metrics with a common set of labels.
357
+ // The metrics can be of any type (counter, gauge, histogram, etc) and are
358
+ // all managed by a single instance of the QueryableDomain.
359
+ // QueryableDomain is the base class for InstrumentDomainImpl, and contains
360
+ // common functionality that doesn't need to know about exact types.
361
+ class QueryableDomain {
362
+ public:
363
+ // Iterate all metric descriptions in all domains.
364
+ static void ForEachInstrument(
365
+ absl::FunctionRef<void(const InstrumentMetadata::Description*)> fn);
366
+
367
+ // Returns the names of the labels in the domain.
368
+ absl::Span<const std::string> label_names() const { return label_names_; }
369
+
370
+ // Reset the internal state of all domains. For test use only.
371
+ static void TestOnlyResetAll();
372
+ // Reset the internal state of this domain. For test use only.
373
+ void TestOnlyReset();
374
+
375
+ static std::unique_ptr<CollectionScope> CreateCollectionScope();
376
+ size_t TestOnlyCountStorageHeld() const;
377
+
378
+ protected:
379
+ QueryableDomain(std::vector<std::string> label_names, size_t map_shards_size)
380
+ : label_names_(std::move(label_names)),
381
+ map_shards_size_(label_names_.empty() ? 1 : map_shards_size),
382
+ map_shards_(std::make_unique<MapShard[]>(map_shards_size_)) {}
383
+
384
+ // QueryableDomain should never be destroyed.
385
+ ~QueryableDomain() { LOG(FATAL) << "QueryableDomain destroyed."; }
386
+
387
+ RefCountedPtr<DomainStorage> GetDomainStorage(std::vector<std::string> label);
388
+
389
+ // Called by InstrumentDomain when construction is complete.
390
+ void Constructed();
391
+
392
+ // Allocates a counter with the given name, description, and unit.
393
+ const InstrumentMetadata::Description* AllocateCounter(
394
+ absl::string_view name, absl::string_view description,
395
+ absl::string_view unit);
396
+ const InstrumentMetadata::Description* AllocateHistogram(
397
+ absl::string_view name, absl::string_view description,
398
+ absl::string_view unit, HistogramBuckets bounds);
399
+ const InstrumentMetadata::Description* AllocateDoubleGauge(
400
+ absl::string_view name, absl::string_view description,
401
+ absl::string_view unit);
402
+ const InstrumentMetadata::Description* AllocateIntGauge(
403
+ absl::string_view name, absl::string_view description,
404
+ absl::string_view unit);
405
+ const InstrumentMetadata::Description* AllocateUintGauge(
406
+ absl::string_view name, absl::string_view description,
407
+ absl::string_view unit);
408
+
409
+ // Returns the number of slots allocated for each metric type.
410
+ uint64_t allocated_counter_slots() const { return allocated_counter_slots_; }
411
+ uint64_t allocated_double_gauge_slots() const {
412
+ return allocated_double_gauge_slots_;
413
+ }
414
+ uint64_t allocated_int_gauge_slots() const {
415
+ return allocated_int_gauge_slots_;
416
+ }
417
+ uint64_t allocated_uint_gauge_slots() const {
418
+ return allocated_uint_gauge_slots_;
419
+ }
420
+
421
+ private:
422
+ friend class StorageSet;
423
+ friend class DomainStorage;
424
+ friend class GaugeStorage;
425
+
426
+ struct MapShard {
427
+ mutable Mutex mu;
428
+ AVL<absl::Span<const std::string>, WeakRefCountedPtr<DomainStorage>>
429
+ storage_map ABSL_GUARDED_BY(mu);
430
+ };
431
+
432
+ void RegisterStorageSet(StorageSet* storage_set);
433
+ void UnregisterStorageSet(StorageSet* storage_set);
434
+
435
+ std::unique_ptr<StorageSet> CreateStorageSet();
436
+ virtual RefCountedPtr<DomainStorage> CreateDomainStorage(
437
+ std::vector<std::string> label) = 0;
438
+ void DomainStorageOrphaned(DomainStorage* storage);
439
+ MapShard& GetMapShard(absl::Span<const std::string> label);
440
+
441
+ // Allocate `size` elements in the domain.
442
+ // Counters will allocate one element. Histograms will allocate one per
443
+ // bucket.
444
+ uint64_t AllocateCounterSlots(size_t size) {
445
+ const uint64_t offset = allocated_counter_slots_;
446
+ allocated_counter_slots_ += size;
447
+ return offset;
448
+ }
449
+
450
+ // We keep a linked list of all QueryableDomains, so that we can walk
451
+ // them in order to export metrics.
452
+ static inline QueryableDomain* last_ = nullptr;
453
+ QueryableDomain* prev_ = nullptr;
454
+
455
+ const std::vector<std::string> label_names_;
456
+ std::vector<const InstrumentMetadata::Description*> metrics_;
457
+ uint64_t allocated_counter_slots_ = 0;
458
+ uint64_t allocated_double_gauge_slots_ = 0;
459
+ uint64_t allocated_int_gauge_slots_ = 0;
460
+ uint64_t allocated_uint_gauge_slots_ = 0;
461
+
462
+ Mutex storage_sets_mu_;
463
+ std::vector<StorageSet*> storage_sets_ ABSL_GUARDED_BY(storage_sets_mu_);
464
+
465
+ const size_t map_shards_size_;
466
+ std::unique_ptr<MapShard[]> map_shards_;
467
+
468
+ mutable Mutex active_storage_sets_mu_;
469
+ std::vector<StorageSet*> active_storage_sets_
470
+ ABSL_GUARDED_BY(active_storage_sets_mu_);
471
+ };
472
+
473
+ // An InstrumentDomain is a collection of metrics with a common set of labels.
474
+ // The metrics can be of any type (counter, gauge, histogram, etc) and are
475
+ // all managed by a single instance of the InstrumentDomain.
476
+ // InstrumentDomains should be created at static initialization time.
477
+ // The InstrumentDomainImpl has a Backend, which defines how metrics are
478
+ // accumulated.
479
+ template <typename Backend, size_t N, typename Tag>
480
+ class InstrumentDomainImpl;
481
+
482
+ struct Counter {
483
+ static constexpr size_t buckets() { return 1; }
484
+ Counter operator->() const { return *this; }
485
+ constexpr size_t BucketFor(int64_t /*value*/) const { return 0; }
486
+ };
487
+
488
+ // An InstrumentHandle is a handle to a single metric in an
489
+ // InstrumentDomainImpl. kType is used in using statements to disambiguate
490
+ // between different InstrumentHandle specializations. Backed, Label... are
491
+ // per InstrumentDomainImpl.
492
+ template <typename Shape, typename Domain>
493
+ class InstrumentHandle {
494
+ private:
495
+ friend Domain;
496
+
497
+ InstrumentHandle(Domain* instrument_domain,
498
+ const InstrumentMetadata::Description* description,
499
+ Shape shape)
500
+ : instrument_domain_(instrument_domain),
501
+ offset_(description->offset),
502
+ shape_(std::move(shape)),
503
+ description_(description) {}
504
+
505
+ Domain* instrument_domain_;
506
+ uint64_t offset_;
507
+ GPR_NO_UNIQUE_ADDRESS Shape shape_;
508
+ const InstrumentMetadata::Description* description_ = nullptr;
509
+ };
510
+
511
+ template <typename T>
512
+ using StdString = std::string;
513
+
514
+ template <typename T>
515
+ using ConstCharPtr = const char*;
516
+
517
+ } // namespace instrument_detail
518
+
519
+ // A domain backend for low contention domains.
520
+ // We use a simple array of atomics to back the collection - each increment
521
+ // is a relaxed add.
522
+ class LowContentionBackend final {
523
+ public:
524
+ explicit LowContentionBackend(size_t size);
525
+
526
+ void Increment(size_t index) {
527
+ counters_[index].fetch_add(1, std::memory_order_relaxed);
528
+ }
529
+
530
+ uint64_t Sum(size_t index);
531
+
532
+ private:
533
+ std::unique_ptr<std::atomic<uint64_t>[]> counters_;
534
+ };
535
+
536
+ // A domain backend for high contention domains.
537
+ // We shard the counters to reduce contention: increments happen on a shard
538
+ // selected by the current CPU, and reads need to accumulate across all the
539
+ // shards.
540
+ class HighContentionBackend final {
541
+ public:
542
+ explicit HighContentionBackend(size_t size);
543
+
544
+ void Increment(size_t index) {
545
+ counters_.this_cpu()[index].fetch_add(1, std::memory_order_relaxed);
546
+ }
547
+
548
+ uint64_t Sum(size_t index);
549
+
550
+ private:
551
+ PerCpu<std::unique_ptr<std::atomic<uint64_t>[]>> counters_{
552
+ PerCpuOptions().SetMaxShards(16)};
553
+ };
554
+
555
+ // MetricsSink is an interface for accumulating metrics.
556
+ // Importantly it's the output interface for MetricsQuery.
557
+ class MetricsSink {
558
+ public:
559
+ // Called once per label per metric, with the value of that metric for that
560
+ // label.
561
+ virtual void Counter(absl::Span<const std::string> label,
562
+ absl::string_view name, uint64_t value) = 0;
563
+ virtual void Histogram(absl::Span<const std::string> label,
564
+ absl::string_view name, HistogramBuckets bounds,
565
+ absl::Span<const uint64_t> counts) = 0;
566
+ virtual void DoubleGauge(absl::Span<const std::string> labels,
567
+ absl::string_view name, double value) = 0;
568
+ virtual void IntGauge(absl::Span<const std::string> labels,
569
+ absl::string_view name, int64_t value) = 0;
570
+ virtual void UintGauge(absl::Span<const std::string> labels,
571
+ absl::string_view name, uint64_t value) = 0;
572
+
573
+ protected:
574
+ ~MetricsSink() = default;
575
+ };
576
+
577
+ // A MetricsQuery allows querying across the global set of metrics and
578
+ // fetching their values.
579
+ // Allows a level of filtering so that we only get the values for metrics
580
+ // that match a set of criteria.
581
+ // Also allows collapsing labels (effectively omitting them) and aggregating
582
+ // over the remaining labels.
583
+ class MetricsQuery {
584
+ public:
585
+ // Only include metrics that include `label` and have that label equal to
586
+ // `value`.
587
+ MetricsQuery& WithLabelEq(absl::string_view label, std::string value);
588
+ // Collapse labels, effectively omitting them. Counters are summed over the
589
+ // remaining dimensions, etc.
590
+ MetricsQuery& CollapseLabels(absl::Span<const std::string> labels);
591
+ // Only include metrics that are in `metrics`.
592
+ MetricsQuery& OnlyMetrics(absl::Span<const std::string> metrics);
593
+
594
+ // Returns the metrics that are selected by this query.
595
+ std::optional<absl::Span<const std::string>> selected_metrics() const {
596
+ return only_metrics_;
597
+ }
598
+
599
+ // Adapts `sink` by including the filtering requested, and then calls `fn`
600
+ // with the filtering sink. This is mainly an implementation detail.
601
+ void Apply(absl::Span<const std::string> label_names,
602
+ absl::FunctionRef<void(MetricsSink&)> fn, MetricsSink& sink) const;
603
+
604
+ // Runs the query, outputting the results to `sink`.
605
+ void Run(std::unique_ptr<CollectionScope> scope, MetricsSink& sink) const;
606
+
607
+ private:
608
+ void ApplyLabelChecks(absl::Span<const std::string> label_names,
609
+ absl::FunctionRef<void(MetricsSink&)> fn,
610
+ MetricsSink& sink) const;
611
+
612
+ absl::flat_hash_map<absl::string_view, std::string> label_eqs_;
613
+ std::optional<std::vector<std::string>> only_metrics_;
614
+ absl::flat_hash_set<std::string> collapsed_labels_;
615
+ };
616
+
617
+ namespace instrument_detail {
618
+
619
+ template <typename Shape, typename... Args>
620
+ Shape* GetMemoizedShape(Args&&... args) {
621
+ // Many histograms are created with the same shape, so we try to deduplicate
622
+ // them.
623
+ using ShapeCache = absl::node_hash_map<std::tuple<Args...>, Shape*>;
624
+ static ShapeCache* shape_cache = new ShapeCache();
625
+ auto it =
626
+ shape_cache->find(std::forward_as_tuple(std::forward<Args>(args)...));
627
+ Shape* shape;
628
+ if (it != shape_cache->end()) {
629
+ shape = it->second;
630
+ } else {
631
+ shape = new Shape(std::forward<Args>(args)...);
632
+ shape_cache->emplace(std::forward_as_tuple(std::forward<Args>(args)...),
633
+ shape);
634
+ }
635
+ return shape;
636
+ }
637
+
638
+ // An InstrumentDomainImpl is a collection of instruments with a common set of
639
+ // labels.
640
+ template <typename Backend, size_t N, typename Tag>
641
+ class InstrumentDomainImpl final : public QueryableDomain {
642
+ public:
643
+ using Self = InstrumentDomainImpl<Backend, N, Tag>;
644
+ using CounterHandle = InstrumentHandle<Counter, Self>;
645
+ using DoubleGaugeHandle =
646
+ InstrumentHandle<InstrumentMetadata::DoubleGaugeShape, Self>;
647
+ using IntGaugeHandle =
648
+ InstrumentHandle<InstrumentMetadata::IntGaugeShape, Self>;
649
+ using UintGaugeHandle =
650
+ InstrumentHandle<InstrumentMetadata::UintGaugeShape, Self>;
651
+ template <typename Shape>
652
+ using HistogramHandle = InstrumentHandle<const Shape*, Self>;
653
+
654
+ class GaugeSink {
655
+ public:
656
+ explicit GaugeSink(GaugeStorage& storage) : storage_(storage) {}
657
+
658
+ void Set(InstrumentHandle<InstrumentMetadata::DoubleGaugeShape, Self> g,
659
+ double x) {
660
+ storage_.SetDouble(g.offset_, x);
661
+ }
662
+ void Set(InstrumentHandle<InstrumentMetadata::IntGaugeShape, Self> g,
663
+ int64_t x) {
664
+ storage_.SetInt(g.offset_, x);
665
+ }
666
+ void Set(InstrumentHandle<InstrumentMetadata::UintGaugeShape, Self> g,
667
+ uint64_t x) {
668
+ storage_.SetUint(g.offset_, x);
669
+ }
670
+
671
+ private:
672
+ GaugeStorage& storage_;
673
+ };
674
+
675
+ class Storage;
676
+
677
+ // Interface for objects that provide gauge values for this domain.
678
+ class GaugeProvider {
679
+ public:
680
+ virtual void PopulateGaugeData(GaugeSink& sink) = 0;
681
+
682
+ protected:
683
+ explicit GaugeProvider(RefCountedPtr<Storage> storage)
684
+ : storage_(std::move(storage)) {
685
+ DCHECK(storage_ != nullptr);
686
+ }
687
+ ~GaugeProvider() { DCHECK(storage_ == nullptr); }
688
+
689
+ void ProviderConstructed() {
690
+ DCHECK(storage_ != nullptr);
691
+ storage_->RegisterGaugeProvider(this);
692
+ }
693
+ void ProviderDestructing() {
694
+ DCHECK(storage_ != nullptr);
695
+ storage_->UnregisterGaugeProvider(this);
696
+ storage_.reset();
697
+ }
698
+
699
+ private:
700
+ RefCountedPtr<Storage> storage_;
701
+ };
702
+
703
+ // Storage is a ref-counted object that holds the backend for an
704
+ // InstrumentDomain for a single set of labels.
705
+ class Storage final : public DomainStorage {
706
+ public:
707
+ ~Storage() override = default;
708
+
709
+ // Increments the counter specified by `handle` by 1 for this storages
710
+ // labels.
711
+ void Increment(CounterHandle handle) {
712
+ DCHECK_EQ(handle.instrument_domain_, domain());
713
+ backend_.Increment(handle.offset_);
714
+ }
715
+
716
+ template <typename Shape>
717
+ void Increment(const HistogramHandle<Shape>& handle, int64_t value) {
718
+ DCHECK_EQ(handle.instrument_domain_, domain());
719
+ CallHistogramCollectionHooks(handle.description_, label(), value);
720
+ backend_.Increment(handle.offset_ + handle.shape_->BucketFor(value));
721
+ }
722
+
723
+ private:
724
+ friend class InstrumentDomainImpl<Backend, N, Tag>;
725
+ friend class GaugeProvider;
726
+
727
+ explicit Storage(InstrumentDomainImpl* instrument_domain,
728
+ std::vector<std::string> labels)
729
+ : DomainStorage(instrument_domain, std::move(labels)),
730
+ backend_(instrument_domain->allocated_counter_slots()) {}
731
+
732
+ uint64_t SumCounter(size_t offset) override { return backend_.Sum(offset); }
733
+
734
+ void RegisterGaugeProvider(GaugeProvider* provider) {
735
+ MutexLock lock(&gauge_providers_mu_);
736
+ gauge_providers_.push_back(provider);
737
+ }
738
+
739
+ void UnregisterGaugeProvider(GaugeProvider* provider) {
740
+ MutexLock lock(&gauge_providers_mu_);
741
+ gauge_providers_.erase(std::remove(gauge_providers_.begin(),
742
+ gauge_providers_.end(), provider),
743
+ gauge_providers_.end());
744
+ }
745
+
746
+ void FillGaugeStorage(GaugeStorage& storage) override {
747
+ GaugeSink sink(storage);
748
+ MutexLock lock(&gauge_providers_mu_);
749
+ for (auto* provider : gauge_providers_) {
750
+ provider->PopulateGaugeData(sink);
751
+ }
752
+ }
753
+
754
+ Backend backend_;
755
+ Mutex gauge_providers_mu_;
756
+ std::vector<GaugeProvider*> gauge_providers_
757
+ ABSL_GUARDED_BY(gauge_providers_mu_);
758
+ };
759
+
760
+ GPR_ATTRIBUTE_NOINLINE explicit InstrumentDomainImpl(
761
+ std::vector<std::string> label_names,
762
+ size_t map_shards = std::min(16u, gpr_cpu_num_cores()))
763
+ : QueryableDomain(std::move(label_names), map_shards) {
764
+ CHECK_EQ(this->label_names().size(), N);
765
+ Constructed();
766
+ }
767
+
768
+ // Registration functions: must all complete before the first GetStorage call.
769
+ // No locking is performed, so registrations must be performed with external
770
+ // synchronization.
771
+ // Effectively: Do this at static initialization time.
772
+
773
+ CounterHandle RegisterCounter(absl::string_view name,
774
+ absl::string_view description,
775
+ absl::string_view unit) {
776
+ return CounterHandle{this, AllocateCounter(name, description, unit),
777
+ Counter{}};
778
+ }
779
+
780
+ template <typename Shape, typename... Args>
781
+ HistogramHandle<Shape> RegisterHistogram(absl::string_view name,
782
+ absl::string_view description,
783
+ absl::string_view unit,
784
+ Args&&... args) {
785
+ auto* shape = GetMemoizedShape<Shape>(std::forward<Args>(args)...);
786
+ const auto* desc =
787
+ AllocateHistogram(name, description, unit, shape->bounds());
788
+ return HistogramHandle<Shape>{this, desc, shape};
789
+ }
790
+
791
+ DoubleGaugeHandle RegisterDoubleGauge(absl::string_view name,
792
+ absl::string_view description,
793
+ absl::string_view unit) {
794
+ return DoubleGaugeHandle{this, AllocateDoubleGauge(name, description, unit),
795
+ InstrumentMetadata::DoubleGaugeShape{}};
796
+ }
797
+
798
+ IntGaugeHandle RegisterIntGauge(absl::string_view name,
799
+ absl::string_view description,
800
+ absl::string_view unit) {
801
+ return IntGaugeHandle{this, AllocateIntGauge(name, description, unit),
802
+ InstrumentMetadata::IntGaugeShape{}};
803
+ }
804
+
805
+ UintGaugeHandle RegisterUintGauge(absl::string_view name,
806
+ absl::string_view description,
807
+ absl::string_view unit) {
808
+ return UintGaugeHandle{this, AllocateUintGauge(name, description, unit),
809
+ InstrumentMetadata::UintGaugeShape{}};
810
+ }
811
+
812
+ // GetStorage: returns a pointer to the storage for the given key, creating
813
+ // it if necessary.
814
+ template <typename... Args>
815
+ RefCountedPtr<Storage> GetStorage(Args&&... labels) {
816
+ static_assert(sizeof...(Args) == N, "Incorrect number of labels provided");
817
+ std::vector<std::string> label_names;
818
+ label_names.reserve(N);
819
+ (label_names.emplace_back(absl::StrCat(labels)), ...);
820
+ return DownCastRefCountedPtr<Storage>(
821
+ GetDomainStorage(std::move(label_names)));
822
+ }
823
+
824
+ RefCountedPtr<DomainStorage> CreateDomainStorage(
825
+ std::vector<std::string> labels) override {
826
+ return RefCountedPtr<Storage>(new Storage(this, std::move(labels)));
827
+ }
828
+
829
+ private:
830
+ ~InstrumentDomainImpl() = delete;
831
+ };
832
+
833
+ class MakeLabel {
834
+ public:
835
+ template <typename... LabelNames>
836
+ auto operator()(LabelNames... t) {
837
+ return std::vector<std::string>{absl::StrCat(t)...};
838
+ }
839
+ };
840
+
841
+ template <typename... LabelNames>
842
+ GPR_ATTRIBUTE_NOINLINE auto MakeLabelFromTuple(
843
+ std::tuple<LabelNames...> t) noexcept {
844
+ return std::apply(MakeLabel(), t);
845
+ }
846
+ } // namespace instrument_detail
847
+
848
+ template <class Derived>
849
+ class InstrumentDomain {
850
+ public:
851
+ static auto* Domain() {
852
+ static auto* domain = new instrument_detail::InstrumentDomainImpl<
853
+ typename Derived::Backend,
854
+ std::tuple_size_v<decltype(Derived::kLabels)>, Derived>(
855
+ instrument_detail::MakeLabelFromTuple(Derived::kLabels));
856
+ return domain;
857
+ }
858
+
859
+ // Returns an InstrumentStorageRefPtr<Derived>.
860
+ template <typename... Args>
861
+ static auto GetStorage(Args&&... labels) {
862
+ return Domain()->GetStorage(std::forward<Args>(labels)...);
863
+ }
864
+
865
+ protected:
866
+ template <typename... Label>
867
+ static constexpr auto Labels(Label... labels) {
868
+ return std::tuple<instrument_detail::ConstCharPtr<Label>...>{labels...};
869
+ }
870
+
871
+ static auto RegisterCounter(absl::string_view name,
872
+ absl::string_view description,
873
+ absl::string_view unit) {
874
+ return Domain()->RegisterCounter(name, description, unit);
875
+ }
876
+
877
+ template <typename Shape, typename... Args>
878
+ static auto RegisterHistogram(absl::string_view name,
879
+ absl::string_view description,
880
+ absl::string_view unit, Args&&... args) {
881
+ return Domain()->template RegisterHistogram<Shape>(
882
+ name, description, unit, std::forward<Args>(args)...);
883
+ }
884
+
885
+ static auto RegisterDoubleGauge(absl::string_view name,
886
+ absl::string_view description,
887
+ absl::string_view unit) {
888
+ return Domain()->RegisterDoubleGauge(name, description, unit);
889
+ }
890
+
891
+ static auto RegisterIntGauge(absl::string_view name,
892
+ absl::string_view description,
893
+ absl::string_view unit) {
894
+ return Domain()->RegisterIntGauge(name, description, unit);
895
+ }
896
+
897
+ static auto RegisterUintGauge(absl::string_view name,
898
+ absl::string_view description,
899
+ absl::string_view unit) {
900
+ return Domain()->RegisterUintGauge(name, description, unit);
901
+ }
902
+
903
+ private:
904
+ InstrumentDomain() = delete;
905
+ };
906
+
907
+ template <typename DomainType>
908
+ using InstrumentDomainImpl =
909
+ std::remove_pointer_t<decltype(DomainType::Domain())>;
910
+
911
+ template <typename DomainType>
912
+ using InstrumentStorage = typename InstrumentDomainImpl<DomainType>::Storage;
913
+
914
+ template <typename DomainType>
915
+ using InstrumentStorageRefPtr = RefCountedPtr<InstrumentStorage<DomainType>>;
916
+
917
+ template <typename DomainType>
918
+ using GaugeSink = typename InstrumentDomainImpl<DomainType>::GaugeSink;
919
+
920
+ template <typename DomainType>
921
+ using GaugeProvider = typename InstrumentDomainImpl<DomainType>::GaugeProvider;
922
+
923
+ // Reset all registered instruments. For test use only.
924
+ void TestOnlyResetInstruments();
925
+
926
+ inline std::unique_ptr<CollectionScope> CreateCollectionScope() {
927
+ return instrument_detail::QueryableDomain::CreateCollectionScope();
928
+ }
929
+
930
+ } // namespace grpc_core
931
+
932
+ #endif // GRPC_SRC_CORE_TELEMETRY_INSTRUMENT_H