Initial commit

Picks up work from https://github.com/grpc/grpc/pull/10259.
A merge was impossible due to the many sweeping changed that
have occured since I last touched that PR (c++-ization, exec_ctx,
reorganitation of filters, etc).
reviewable/pr13883/r1
ncteisen 7 years ago
parent 2e04b2dd0c
commit 7d9b6358b5
  1. 39
      CMakeLists.txt
  2. 45
      Makefile
  3. 17
      build.yaml
  4. 2
      config.m4
  5. 2
      config.w32
  6. 8
      gRPC-Core.podspec
  7. 4
      grpc.gemspec
  8. 7
      grpc.gyp
  9. 3
      include/grpc/impl/codegen/grpc_types.h
  10. 4
      package.xml
  11. 17
      src/core/ext/filters/client_channel/subchannel.cc
  12. 4
      src/core/ext/filters/client_channel/subchannel.h
  13. 326
      src/core/lib/channel/channel_tracer.cc
  14. 78
      src/core/lib/channel/channel_tracer.h
  15. 36
      src/core/lib/json/json.cc
  16. 21
      src/core/lib/json/json.h
  17. 100
      src/core/lib/support/object_registry.cc
  18. 39
      src/core/lib/support/object_registry.h
  19. 33
      src/core/lib/surface/channel.cc
  20. 3
      src/core/lib/surface/channel.h
  21. 3
      src/core/lib/surface/init.cc
  22. 2
      src/python/grpcio/grpc_core_dependencies.py
  23. 210
      test/core/channel/channel_tracer_test.cc
  24. 60
      test/core/util/channel_tracing_utils.cc
  25. 30
      test/core/util/channel_tracing_utils.h
  26. 2
      tools/doxygen/Doxyfile.c++.internal
  27. 4
      tools/doxygen/Doxyfile.core.internal
  28. 26
      tools/run_tests/generated/sources_and_headers.json
  29. 24
      tools/run_tests/generated/tests.json

@ -274,6 +274,7 @@ add_dependencies(buildtests_c grpc_byte_buffer_reader_test)
add_dependencies(buildtests_c grpc_channel_args_test)
add_dependencies(buildtests_c grpc_channel_stack_builder_test)
add_dependencies(buildtests_c grpc_channel_stack_test)
add_dependencies(buildtests_c grpc_channel_tracer_test)
add_dependencies(buildtests_c grpc_completion_queue_test)
add_dependencies(buildtests_c grpc_completion_queue_threading_test)
add_dependencies(buildtests_c grpc_credentials_test)
@ -639,6 +640,7 @@ add_library(gpr
src/core/lib/support/log_windows.cc
src/core/lib/support/mpscq.cc
src/core/lib/support/murmur_hash.cc
src/core/lib/support/object_registry.cc
src/core/lib/support/string.cc
src/core/lib/support/string_posix.cc
src/core/lib/support/string_util_windows.cc
@ -793,6 +795,7 @@ add_library(grpc
src/core/lib/channel/channel_args.cc
src/core/lib/channel/channel_stack.cc
src/core/lib/channel/channel_stack_builder.cc
src/core/lib/channel/channel_tracer.cc
src/core/lib/channel/connected_channel.cc
src/core/lib/channel/handshaker.cc
src/core/lib/channel/handshaker_factory.cc
@ -1136,6 +1139,7 @@ add_library(grpc_cronet
src/core/lib/channel/channel_args.cc
src/core/lib/channel/channel_stack.cc
src/core/lib/channel/channel_stack_builder.cc
src/core/lib/channel/channel_tracer.cc
src/core/lib/channel/connected_channel.cc
src/core/lib/channel/handshaker.cc
src/core/lib/channel/handshaker_factory.cc
@ -1445,6 +1449,7 @@ add_library(grpc_test_util
test/core/end2end/fixtures/http_proxy_fixture.cc
test/core/end2end/fixtures/proxy.cc
test/core/iomgr/endpoint_tests.cc
test/core/util/channel_tracing_utils.cc
test/core/util/debugger_macros.cc
test/core/util/grpc_profiler.cc
test/core/util/histogram.cc
@ -1462,6 +1467,7 @@ add_library(grpc_test_util
src/core/lib/channel/channel_args.cc
src/core/lib/channel/channel_stack.cc
src/core/lib/channel/channel_stack_builder.cc
src/core/lib/channel/channel_tracer.cc
src/core/lib/channel/connected_channel.cc
src/core/lib/channel/handshaker.cc
src/core/lib/channel/handshaker_factory.cc
@ -1715,6 +1721,7 @@ add_library(grpc_test_util_unsecure
test/core/end2end/fixtures/http_proxy_fixture.cc
test/core/end2end/fixtures/proxy.cc
test/core/iomgr/endpoint_tests.cc
test/core/util/channel_tracing_utils.cc
test/core/util/debugger_macros.cc
test/core/util/grpc_profiler.cc
test/core/util/histogram.cc
@ -1732,6 +1739,7 @@ add_library(grpc_test_util_unsecure
src/core/lib/channel/channel_args.cc
src/core/lib/channel/channel_stack.cc
src/core/lib/channel/channel_stack_builder.cc
src/core/lib/channel/channel_tracer.cc
src/core/lib/channel/connected_channel.cc
src/core/lib/channel/handshaker.cc
src/core/lib/channel/handshaker_factory.cc
@ -1985,6 +1993,7 @@ add_library(grpc_unsecure
src/core/lib/channel/channel_args.cc
src/core/lib/channel/channel_stack.cc
src/core/lib/channel/channel_stack_builder.cc
src/core/lib/channel/channel_tracer.cc
src/core/lib/channel/connected_channel.cc
src/core/lib/channel/handshaker.cc
src/core/lib/channel/handshaker_factory.cc
@ -2735,6 +2744,7 @@ add_library(grpc++_cronet
src/core/lib/channel/channel_args.cc
src/core/lib/channel/channel_stack.cc
src/core/lib/channel/channel_stack_builder.cc
src/core/lib/channel/channel_tracer.cc
src/core/lib/channel/connected_channel.cc
src/core/lib/channel/handshaker.cc
src/core/lib/channel/handshaker_factory.cc
@ -6348,6 +6358,35 @@ target_link_libraries(grpc_channel_stack_test
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(grpc_channel_tracer_test
test/core/channel/channel_tracer_test.cc
)
target_include_directories(grpc_channel_tracer_test
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
PRIVATE ${PROTOBUF_ROOT_DIR}/src
PRIVATE ${BENCHMARK_ROOT_DIR}/include
PRIVATE ${ZLIB_ROOT_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
PRIVATE ${CARES_INCLUDE_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
)
target_link_libraries(grpc_channel_tracer_test
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
grpc
gpr_test_util
gpr
)
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
add_executable(grpc_completion_queue_test
test/core/surface/completion_queue_test.cc
)

@ -1001,6 +1001,7 @@ grpc_byte_buffer_reader_test: $(BINDIR)/$(CONFIG)/grpc_byte_buffer_reader_test
grpc_channel_args_test: $(BINDIR)/$(CONFIG)/grpc_channel_args_test
grpc_channel_stack_builder_test: $(BINDIR)/$(CONFIG)/grpc_channel_stack_builder_test
grpc_channel_stack_test: $(BINDIR)/$(CONFIG)/grpc_channel_stack_test
grpc_channel_tracer_test: $(BINDIR)/$(CONFIG)/grpc_channel_tracer_test
grpc_completion_queue_test: $(BINDIR)/$(CONFIG)/grpc_completion_queue_test
grpc_completion_queue_threading_test: $(BINDIR)/$(CONFIG)/grpc_completion_queue_threading_test
grpc_create_jwt: $(BINDIR)/$(CONFIG)/grpc_create_jwt
@ -1400,6 +1401,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/grpc_channel_args_test \
$(BINDIR)/$(CONFIG)/grpc_channel_stack_builder_test \
$(BINDIR)/$(CONFIG)/grpc_channel_stack_test \
$(BINDIR)/$(CONFIG)/grpc_channel_tracer_test \
$(BINDIR)/$(CONFIG)/grpc_completion_queue_test \
$(BINDIR)/$(CONFIG)/grpc_completion_queue_threading_test \
$(BINDIR)/$(CONFIG)/grpc_credentials_test \
@ -1865,6 +1867,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/grpc_channel_stack_builder_test || ( echo test grpc_channel_stack_builder_test failed ; exit 1 )
$(E) "[RUN] Testing grpc_channel_stack_test"
$(Q) $(BINDIR)/$(CONFIG)/grpc_channel_stack_test || ( echo test grpc_channel_stack_test failed ; exit 1 )
$(E) "[RUN] Testing grpc_channel_tracer_test"
$(Q) $(BINDIR)/$(CONFIG)/grpc_channel_tracer_test || ( echo test grpc_channel_tracer_test failed ; exit 1 )
$(E) "[RUN] Testing grpc_completion_queue_test"
$(Q) $(BINDIR)/$(CONFIG)/grpc_completion_queue_test || ( echo test grpc_completion_queue_test failed ; exit 1 )
$(E) "[RUN] Testing grpc_completion_queue_threading_test"
@ -2843,6 +2847,7 @@ LIBGPR_SRC = \
src/core/lib/support/log_windows.cc \
src/core/lib/support/mpscq.cc \
src/core/lib/support/murmur_hash.cc \
src/core/lib/support/object_registry.cc \
src/core/lib/support/string.cc \
src/core/lib/support/string_posix.cc \
src/core/lib/support/string_util_windows.cc \
@ -2974,6 +2979,7 @@ LIBGRPC_SRC = \
src/core/lib/channel/channel_args.cc \
src/core/lib/channel/channel_stack.cc \
src/core/lib/channel/channel_stack_builder.cc \
src/core/lib/channel/channel_tracer.cc \
src/core/lib/channel/connected_channel.cc \
src/core/lib/channel/handshaker.cc \
src/core/lib/channel/handshaker_factory.cc \
@ -3317,6 +3323,7 @@ LIBGRPC_CRONET_SRC = \
src/core/lib/channel/channel_args.cc \
src/core/lib/channel/channel_stack.cc \
src/core/lib/channel/channel_stack_builder.cc \
src/core/lib/channel/channel_tracer.cc \
src/core/lib/channel/connected_channel.cc \
src/core/lib/channel/handshaker.cc \
src/core/lib/channel/handshaker_factory.cc \
@ -3625,6 +3632,7 @@ LIBGRPC_TEST_UTIL_SRC = \
test/core/end2end/fixtures/http_proxy_fixture.cc \
test/core/end2end/fixtures/proxy.cc \
test/core/iomgr/endpoint_tests.cc \
test/core/util/channel_tracing_utils.cc \
test/core/util/debugger_macros.cc \
test/core/util/grpc_profiler.cc \
test/core/util/histogram.cc \
@ -3642,6 +3650,7 @@ LIBGRPC_TEST_UTIL_SRC = \
src/core/lib/channel/channel_args.cc \
src/core/lib/channel/channel_stack.cc \
src/core/lib/channel/channel_stack_builder.cc \
src/core/lib/channel/channel_tracer.cc \
src/core/lib/channel/connected_channel.cc \
src/core/lib/channel/handshaker.cc \
src/core/lib/channel/handshaker_factory.cc \
@ -3886,6 +3895,7 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \
test/core/end2end/fixtures/http_proxy_fixture.cc \
test/core/end2end/fixtures/proxy.cc \
test/core/iomgr/endpoint_tests.cc \
test/core/util/channel_tracing_utils.cc \
test/core/util/debugger_macros.cc \
test/core/util/grpc_profiler.cc \
test/core/util/histogram.cc \
@ -3903,6 +3913,7 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \
src/core/lib/channel/channel_args.cc \
src/core/lib/channel/channel_stack.cc \
src/core/lib/channel/channel_stack_builder.cc \
src/core/lib/channel/channel_tracer.cc \
src/core/lib/channel/connected_channel.cc \
src/core/lib/channel/handshaker.cc \
src/core/lib/channel/handshaker_factory.cc \
@ -4134,6 +4145,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/channel/channel_args.cc \
src/core/lib/channel/channel_stack.cc \
src/core/lib/channel/channel_stack_builder.cc \
src/core/lib/channel/channel_tracer.cc \
src/core/lib/channel/connected_channel.cc \
src/core/lib/channel/handshaker.cc \
src/core/lib/channel/handshaker_factory.cc \
@ -4867,6 +4879,7 @@ LIBGRPC++_CRONET_SRC = \
src/core/lib/channel/channel_args.cc \
src/core/lib/channel/channel_stack.cc \
src/core/lib/channel/channel_stack_builder.cc \
src/core/lib/channel/channel_tracer.cc \
src/core/lib/channel/connected_channel.cc \
src/core/lib/channel/handshaker.cc \
src/core/lib/channel/handshaker_factory.cc \
@ -10516,6 +10529,38 @@ endif
endif
GRPC_CHANNEL_TRACER_TEST_SRC = \
test/core/channel/channel_tracer_test.cc \
GRPC_CHANNEL_TRACER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_CHANNEL_TRACER_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/grpc_channel_tracer_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/grpc_channel_tracer_test: $(GRPC_CHANNEL_TRACER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(GRPC_CHANNEL_TRACER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/grpc_channel_tracer_test
endif
$(OBJDIR)/$(CONFIG)/test/core/channel/channel_tracer_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_grpc_channel_tracer_test: $(GRPC_CHANNEL_TRACER_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(GRPC_CHANNEL_TRACER_TEST_OBJS:.o=.dep)
endif
endif
GRPC_COMPLETION_QUEUE_TEST_SRC = \
test/core/surface/completion_queue_test.cc \

@ -49,6 +49,7 @@ filegroups:
- src/core/lib/support/log_windows.cc
- src/core/lib/support/mpscq.cc
- src/core/lib/support/murmur_hash.cc
- src/core/lib/support/object_registry.cc
- src/core/lib/support/string.cc
- src/core/lib/support/string_posix.cc
- src/core/lib/support/string_util_windows.cc
@ -113,6 +114,7 @@ filegroups:
- src/core/lib/support/memory.h
- src/core/lib/support/mpscq.h
- src/core/lib/support/murmur_hash.h
- src/core/lib/support/object_registry.h
- src/core/lib/support/spinlock.h
- src/core/lib/support/string.h
- src/core/lib/support/string_windows.h
@ -154,6 +156,7 @@ filegroups:
- src/core/lib/channel/channel_args.cc
- src/core/lib/channel/channel_stack.cc
- src/core/lib/channel/channel_stack_builder.cc
- src/core/lib/channel/channel_tracer.cc
- src/core/lib/channel/connected_channel.cc
- src/core/lib/channel/handshaker.cc
- src/core/lib/channel/handshaker_factory.cc
@ -309,6 +312,7 @@ filegroups:
- src/core/lib/channel/channel_args.h
- src/core/lib/channel/channel_stack.h
- src/core/lib/channel/channel_stack_builder.h
- src/core/lib/channel/channel_tracer.h
- src/core/lib/channel/connected_channel.h
- src/core/lib/channel/context.h
- src/core/lib/channel/handshaker.h
@ -710,6 +714,7 @@ filegroups:
- test/core/end2end/fixtures/http_proxy_fixture.h
- test/core/end2end/fixtures/proxy.h
- test/core/iomgr/endpoint_tests.h
- test/core/util/channel_tracing_utils.h
- test/core/util/debugger_macros.h
- test/core/util/grpc_profiler.h
- test/core/util/histogram.h
@ -728,6 +733,7 @@ filegroups:
- test/core/end2end/fixtures/http_proxy_fixture.cc
- test/core/end2end/fixtures/proxy.cc
- test/core/iomgr/endpoint_tests.cc
- test/core/util/channel_tracing_utils.cc
- test/core/util/debugger_macros.cc
- test/core/util/grpc_profiler.cc
- test/core/util/histogram.cc
@ -2333,6 +2339,17 @@ targets:
- gpr_test_util
- gpr
uses_polling: false
- name: grpc_channel_tracer_test
build: test
language: c
src:
- test/core/channel/channel_tracer_test.cc
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
uses_polling: false
- name: grpc_completion_queue_test
build: test
language: c

@ -62,6 +62,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/support/log_windows.cc \
src/core/lib/support/mpscq.cc \
src/core/lib/support/murmur_hash.cc \
src/core/lib/support/object_registry.cc \
src/core/lib/support/string.cc \
src/core/lib/support/string_posix.cc \
src/core/lib/support/string_util_windows.cc \
@ -88,6 +89,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/channel/channel_args.cc \
src/core/lib/channel/channel_stack.cc \
src/core/lib/channel/channel_stack_builder.cc \
src/core/lib/channel/channel_tracer.cc \
src/core/lib/channel/connected_channel.cc \
src/core/lib/channel/handshaker.cc \
src/core/lib/channel/handshaker_factory.cc \

@ -39,6 +39,7 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\support\\log_windows.cc " +
"src\\core\\lib\\support\\mpscq.cc " +
"src\\core\\lib\\support\\murmur_hash.cc " +
"src\\core\\lib\\support\\object_registry.cc " +
"src\\core\\lib\\support\\string.cc " +
"src\\core\\lib\\support\\string_posix.cc " +
"src\\core\\lib\\support\\string_util_windows.cc " +
@ -65,6 +66,7 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\channel\\channel_args.cc " +
"src\\core\\lib\\channel\\channel_stack.cc " +
"src\\core\\lib\\channel\\channel_stack_builder.cc " +
"src\\core\\lib\\channel\\channel_tracer.cc " +
"src\\core\\lib\\channel\\connected_channel.cc " +
"src\\core\\lib\\channel\\handshaker.cc " +
"src\\core\\lib\\channel\\handshaker_factory.cc " +

@ -205,6 +205,7 @@ Pod::Spec.new do |s|
'src/core/lib/support/memory.h',
'src/core/lib/support/mpscq.h',
'src/core/lib/support/murmur_hash.h',
'src/core/lib/support/object_registry.h',
'src/core/lib/support/spinlock.h',
'src/core/lib/support/string.h',
'src/core/lib/support/string_windows.h',
@ -234,6 +235,7 @@ Pod::Spec.new do |s|
'src/core/lib/support/log_windows.cc',
'src/core/lib/support/mpscq.cc',
'src/core/lib/support/murmur_hash.cc',
'src/core/lib/support/object_registry.cc',
'src/core/lib/support/string.cc',
'src/core/lib/support/string_posix.cc',
'src/core/lib/support/string_util_windows.cc',
@ -333,6 +335,7 @@ Pod::Spec.new do |s|
'src/core/lib/channel/channel_args.h',
'src/core/lib/channel/channel_stack.h',
'src/core/lib/channel/channel_stack_builder.h',
'src/core/lib/channel/channel_tracer.h',
'src/core/lib/channel/connected_channel.h',
'src/core/lib/channel/context.h',
'src/core/lib/channel/handshaker.h',
@ -473,6 +476,7 @@ Pod::Spec.new do |s|
'src/core/lib/channel/channel_args.cc',
'src/core/lib/channel/channel_stack.cc',
'src/core/lib/channel/channel_stack_builder.cc',
'src/core/lib/channel/channel_tracer.cc',
'src/core/lib/channel/connected_channel.cc',
'src/core/lib/channel/handshaker.cc',
'src/core/lib/channel/handshaker_factory.cc',
@ -729,6 +733,7 @@ Pod::Spec.new do |s|
'src/core/lib/support/memory.h',
'src/core/lib/support/mpscq.h',
'src/core/lib/support/murmur_hash.h',
'src/core/lib/support/object_registry.h',
'src/core/lib/support/spinlock.h',
'src/core/lib/support/string.h',
'src/core/lib/support/string_windows.h',
@ -813,6 +818,7 @@ Pod::Spec.new do |s|
'src/core/lib/channel/channel_args.h',
'src/core/lib/channel/channel_stack.h',
'src/core/lib/channel/channel_stack_builder.h',
'src/core/lib/channel/channel_tracer.h',
'src/core/lib/channel/connected_channel.h',
'src/core/lib/channel/context.h',
'src/core/lib/channel/handshaker.h',
@ -985,6 +991,7 @@ Pod::Spec.new do |s|
'test/core/end2end/fixtures/http_proxy_fixture.cc',
'test/core/end2end/fixtures/proxy.cc',
'test/core/iomgr/endpoint_tests.cc',
'test/core/util/channel_tracing_utils.cc',
'test/core/util/debugger_macros.cc',
'test/core/util/grpc_profiler.cc',
'test/core/util/histogram.cc',
@ -1004,6 +1011,7 @@ Pod::Spec.new do |s|
'test/core/end2end/fixtures/http_proxy_fixture.h',
'test/core/end2end/fixtures/proxy.h',
'test/core/iomgr/endpoint_tests.h',
'test/core/util/channel_tracing_utils.h',
'test/core/util/debugger_macros.h',
'test/core/util/grpc_profiler.h',
'test/core/util/histogram.h',

@ -95,6 +95,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/support/memory.h )
s.files += %w( src/core/lib/support/mpscq.h )
s.files += %w( src/core/lib/support/murmur_hash.h )
s.files += %w( src/core/lib/support/object_registry.h )
s.files += %w( src/core/lib/support/spinlock.h )
s.files += %w( src/core/lib/support/string.h )
s.files += %w( src/core/lib/support/string_windows.h )
@ -124,6 +125,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/support/log_windows.cc )
s.files += %w( src/core/lib/support/mpscq.cc )
s.files += %w( src/core/lib/support/murmur_hash.cc )
s.files += %w( src/core/lib/support/object_registry.cc )
s.files += %w( src/core/lib/support/string.cc )
s.files += %w( src/core/lib/support/string_posix.cc )
s.files += %w( src/core/lib/support/string_util_windows.cc )
@ -259,6 +261,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/channel/channel_args.h )
s.files += %w( src/core/lib/channel/channel_stack.h )
s.files += %w( src/core/lib/channel/channel_stack_builder.h )
s.files += %w( src/core/lib/channel/channel_tracer.h )
s.files += %w( src/core/lib/channel/connected_channel.h )
s.files += %w( src/core/lib/channel/context.h )
s.files += %w( src/core/lib/channel/handshaker.h )
@ -403,6 +406,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/channel/channel_args.cc )
s.files += %w( src/core/lib/channel/channel_stack.cc )
s.files += %w( src/core/lib/channel/channel_stack_builder.cc )
s.files += %w( src/core/lib/channel/channel_tracer.cc )
s.files += %w( src/core/lib/channel/connected_channel.cc )
s.files += %w( src/core/lib/channel/handshaker.cc )
s.files += %w( src/core/lib/channel/handshaker_factory.cc )

@ -181,6 +181,7 @@
'src/core/lib/support/log_windows.cc',
'src/core/lib/support/mpscq.cc',
'src/core/lib/support/murmur_hash.cc',
'src/core/lib/support/object_registry.cc',
'src/core/lib/support/string.cc',
'src/core/lib/support/string_posix.cc',
'src/core/lib/support/string_util_windows.cc',
@ -226,6 +227,7 @@
'src/core/lib/channel/channel_args.cc',
'src/core/lib/channel/channel_stack.cc',
'src/core/lib/channel/channel_stack_builder.cc',
'src/core/lib/channel/channel_tracer.cc',
'src/core/lib/channel/connected_channel.cc',
'src/core/lib/channel/handshaker.cc',
'src/core/lib/channel/handshaker_factory.cc',
@ -503,6 +505,7 @@
'test/core/end2end/fixtures/http_proxy_fixture.cc',
'test/core/end2end/fixtures/proxy.cc',
'test/core/iomgr/endpoint_tests.cc',
'test/core/util/channel_tracing_utils.cc',
'test/core/util/debugger_macros.cc',
'test/core/util/grpc_profiler.cc',
'test/core/util/histogram.cc',
@ -520,6 +523,7 @@
'src/core/lib/channel/channel_args.cc',
'src/core/lib/channel/channel_stack.cc',
'src/core/lib/channel/channel_stack_builder.cc',
'src/core/lib/channel/channel_tracer.cc',
'src/core/lib/channel/connected_channel.cc',
'src/core/lib/channel/handshaker.cc',
'src/core/lib/channel/handshaker_factory.cc',
@ -715,6 +719,7 @@
'test/core/end2end/fixtures/http_proxy_fixture.cc',
'test/core/end2end/fixtures/proxy.cc',
'test/core/iomgr/endpoint_tests.cc',
'test/core/util/channel_tracing_utils.cc',
'test/core/util/debugger_macros.cc',
'test/core/util/grpc_profiler.cc',
'test/core/util/histogram.cc',
@ -732,6 +737,7 @@
'src/core/lib/channel/channel_args.cc',
'src/core/lib/channel/channel_stack.cc',
'src/core/lib/channel/channel_stack_builder.cc',
'src/core/lib/channel/channel_tracer.cc',
'src/core/lib/channel/connected_channel.cc',
'src/core/lib/channel/handshaker.cc',
'src/core/lib/channel/handshaker_factory.cc',
@ -926,6 +932,7 @@
'src/core/lib/channel/channel_args.cc',
'src/core/lib/channel/channel_stack.cc',
'src/core/lib/channel/channel_stack_builder.cc',
'src/core/lib/channel/channel_tracer.cc',
'src/core/lib/channel/connected_channel.cc',
'src/core/lib/channel/handshaker.cc',
'src/core/lib/channel/handshaker_factory.cc',

@ -274,6 +274,9 @@ typedef struct {
#define GRPC_ARG_SOCKET_MUTATOR "grpc.socket_mutator"
/** The grpc_socket_factory instance to create and bind sockets. A pointer. */
#define GRPC_ARG_SOCKET_FACTORY "grpc.socket_factory"
/** The maximum number of trace nodes to keep in the tracer for each channel or
* subchannel. The default is 10. If set to 0, channel tracing is disabled. */
#define GRPC_ARG_CHANNEL_TRACING_MAX_NODES "grpc.channel_tracing_max_nodes"
/** If non-zero, Cronet transport will coalesce packets to fewer frames
* when possible. */
#define GRPC_ARG_USE_CRONET_PACKET_COALESCING \

@ -107,6 +107,7 @@
<file baseinstalldir="/" name="src/core/lib/support/memory.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/mpscq.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/murmur_hash.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/object_registry.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/spinlock.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/string.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/string_windows.h" role="src" />
@ -136,6 +137,7 @@
<file baseinstalldir="/" name="src/core/lib/support/log_windows.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/mpscq.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/murmur_hash.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/object_registry.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/string.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/string_posix.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/string_util_windows.cc" role="src" />
@ -271,6 +273,7 @@
<file baseinstalldir="/" name="src/core/lib/channel/channel_args.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/channel_stack.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/channel_stack_builder.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/channel_tracer.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/connected_channel.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/context.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/handshaker.h" role="src" />
@ -415,6 +418,7 @@
<file baseinstalldir="/" name="src/core/lib/channel/channel_args.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/channel_stack.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/channel_stack_builder.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/channel_tracer.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/connected_channel.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/handshaker.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/handshaker_factory.cc" role="src" />

@ -35,6 +35,7 @@
#include "src/core/ext/filters/client_channel/uri_parser.h"
#include "src/core/lib/backoff/backoff.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_tracer.h"
#include "src/core/lib/channel/connected_channel.h"
#include "src/core/lib/debug/stats.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
@ -42,6 +43,7 @@
#include "src/core/lib/profiling/timers.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/support/manual_constructor.h"
#include "src/core/lib/support/object_registry.h"
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/surface/channel_init.h"
#include "src/core/lib/transport/connectivity_state.h"
@ -75,6 +77,7 @@ typedef struct external_state_watcher {
} external_state_watcher;
struct grpc_subchannel {
intptr_t uuid;
grpc_connector* connector;
/** refcount
@ -131,6 +134,8 @@ struct grpc_subchannel {
bool backoff_begun;
/** our alarm */
grpc_timer alarm;
grpc_channel_tracer* tracer;
};
struct grpc_subchannel_call {
@ -183,6 +188,7 @@ void grpc_connected_subchannel_unref(
static void subchannel_destroy(void* arg, grpc_error* error) {
grpc_subchannel* c = (grpc_subchannel*)arg;
grpc_object_registry_unregister_object(c->uuid);
gpr_free((void*)c->filters);
grpc_channel_args_destroy(c->args);
grpc_connectivity_state_destroy(&c->state_tracker);
@ -337,6 +343,8 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector,
GRPC_STATS_INC_CLIENT_SUBCHANNELS_CREATED();
c = (grpc_subchannel*)gpr_zalloc(sizeof(*c));
c->uuid =
grpc_object_registry_register_object(c, GPRC_OBJECT_REGISTRY_SUBCHANNEL);
c->key = key;
gpr_atm_no_barrier_store(&c->ref_pair, 1 << INTERNAL_REF_BITS);
c->connector = connector;
@ -385,6 +393,15 @@ grpc_subchannel* grpc_subchannel_create(grpc_connector* connector,
return grpc_subchannel_index_register(key, c);
}
char* grpc_subchannel_get_trace(grpc_subchannel* subchannel, bool recursive) {
return subchannel->tracer != NULL
? grpc_channel_tracer_render_trace(subchannel->tracer, recursive)
: NULL;
}
intptr_t grpc_subchannel_get_uuid(grpc_subchannel* subchannel) {
return subchannel->uuid;
}
static void continue_connect_locked(grpc_subchannel* c) {
grpc_connect_in_args args;
args.interested_parties = c->pollset_set;

@ -165,6 +165,10 @@ struct grpc_subchannel_args {
grpc_subchannel* grpc_subchannel_create(grpc_connector* connector,
const grpc_subchannel_args* args);
/// retrieves the trace for this subchannel in JSON form.
char* grpc_subchannel_get_trace(grpc_subchannel* subchannel, bool recursive);
intptr_t grpc_subchannel_get_uuid(grpc_subchannel* subchannel);
/// Sets \a addr from \a args.
void grpc_get_subchannel_address_arg(const grpc_channel_args* args,
grpc_resolved_address* addr);

@ -0,0 +1,326 @@
/*
*
* Copyright 2017 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/channel/channel_tracer.h"
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/useful.h>
#include <stdlib.h>
#include <string.h>
#include "src/core/ext/filters/client_channel/subchannel.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/support/object_registry.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/transport/connectivity_state.h"
// One node of tracing data
typedef struct grpc_trace_node {
grpc_slice data;
grpc_error* error;
gpr_timespec time_created;
grpc_connectivity_state connectivity_state;
struct grpc_trace_node* next;
// the tracer object for the (sub)channel that this trace node refers to.
grpc_channel_tracer* referenced_tracer;
} grpc_trace_node;
/* the channel tracing object */
struct grpc_channel_tracer {
gpr_refcount refs;
gpr_mu tracer_mu;
intptr_t channel_uuid;
uint64_t num_nodes_logged;
size_t list_size;
size_t max_list_size;
grpc_trace_node* head_trace;
grpc_trace_node* tail_trace;
gpr_timespec time_created;
};
#ifdef GRPC_CHANNEL_TRACER_REFCOUNT_DEBUG
grpc_channel_tracer* grpc_channel_tracer_create(size_t max_nodes, intptr_t uuid,
const char* file, int line,
const char* func) {
#else
grpc_channel_tracer* grpc_channel_tracer_create(size_t max_nodes,
intptr_t uuid) {
#endif
grpc_channel_tracer* tracer = static_cast<grpc_channel_tracer*>(
gpr_zalloc(sizeof(grpc_channel_tracer)));
gpr_mu_init(&tracer->tracer_mu);
gpr_ref_init(&tracer->refs, 1);
#ifdef GRPC_CHANNEL_TRACER_REFCOUNT_DEBUG
gpr_log(GPR_DEBUG, "%p create [%s:%d %s]", tracer, file, line, func);
#endif
tracer->channel_uuid = uuid;
tracer->max_list_size = max_nodes;
tracer->time_created = gpr_now(GPR_CLOCK_REALTIME);
return tracer;
}
#ifdef GRPC_CHANNEL_TRACER_REFCOUNT_DEBUG
grpc_channel_tracer* grpc_channel_tracer_ref(grpc_channel_tracer* tracer,
const char* file, int line,
const char* func) {
if (!tracer) return tracer;
gpr_log(GPR_DEBUG, "%p: %" PRIdPTR " -> %" PRIdPTR " [%s:%d %s]", tracer,
gpr_atm_no_barrier_load(&tracer->refs.count),
gpr_atm_no_barrier_load(&tracer->refs.count) + 1, file, line, func);
gpr_ref(&tracer->refs);
return tracer;
}
#else
grpc_channel_tracer* grpc_channel_tracer_ref(grpc_channel_tracer* tracer) {
if (!tracer) return tracer;
gpr_ref(&tracer->refs);
return tracer;
}
#endif
static void free_node(grpc_trace_node* node) {
GRPC_ERROR_UNREF(node->error);
GRPC_CHANNEL_TRACER_UNREF(node->referenced_tracer);
grpc_slice_unref_internal(node->data);
gpr_free(node);
}
static void grpc_channel_tracer_destroy(grpc_channel_tracer* tracer) {
grpc_trace_node* it = tracer->head_trace;
while (it != NULL) {
grpc_trace_node* to_free = it;
it = it->next;
free_node(to_free);
}
gpr_mu_destroy(&tracer->tracer_mu);
gpr_free(tracer);
}
#ifdef GRPC_CHANNEL_TRACER_REFCOUNT_DEBUG
void grpc_channel_tracer_unref(grpc_channel_tracer* tracer, const char* file,
int line, const char* func) {
if (!tracer) return;
gpr_log(GPR_DEBUG, "%p: %" PRIdPTR " -> %" PRIdPTR " [%s:%d %s]", tracer,
gpr_atm_no_barrier_load(&tracer->refs.count),
gpr_atm_no_barrier_load(&tracer->refs.count) - 1, file, line, func);
if (gpr_unref(&tracer->refs)) {
grpc_channel_tracer_destroy(tracer);
}
}
#else
void grpc_channel_tracer_unref(grpc_channel_tracer* tracer) {
if (!tracer) return;
if (gpr_unref(&tracer->refs)) {
grpc_channel_tracer_destroy(tracer);
}
}
#endif
void grpc_channel_tracer_add_trace(grpc_channel_tracer* tracer, grpc_slice data,
grpc_error* error,
grpc_connectivity_state connectivity_state,
grpc_channel_tracer* referenced_tracer) {
if (!tracer) return;
++tracer->num_nodes_logged;
// create and fill up the new node
grpc_trace_node* new_trace_node =
static_cast<grpc_trace_node*>(gpr_malloc(sizeof(grpc_trace_node)));
new_trace_node->data = data;
new_trace_node->error = error;
new_trace_node->time_created = gpr_now(GPR_CLOCK_REALTIME);
new_trace_node->connectivity_state = connectivity_state;
new_trace_node->next = NULL;
new_trace_node->referenced_tracer =
GRPC_CHANNEL_TRACER_REF(referenced_tracer);
// first node case
if (tracer->head_trace == NULL) {
tracer->head_trace = tracer->tail_trace = new_trace_node;
}
// regular node add case
else {
tracer->tail_trace->next = new_trace_node;
tracer->tail_trace = tracer->tail_trace->next;
}
++tracer->list_size;
// maybe garbage collect the end
if (tracer->list_size > tracer->max_list_size) {
grpc_trace_node* to_free = tracer->head_trace;
tracer->head_trace = tracer->head_trace->next;
free_node(to_free);
--tracer->list_size;
}
}
// returns an allocated string that represents tm according to RFC-3339.
static char* fmt_time(gpr_timespec tm) {
char buffer[35];
struct tm* tm_info = localtime((const time_t*)&tm.tv_sec);
strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%S", tm_info);
char* full_time_str;
gpr_asprintf(&full_time_str, "%s.%09dZ", buffer, tm.tv_nsec);
return full_time_str;
}
typedef struct seen_tracers {
grpc_channel_tracer** tracers;
size_t size;
size_t cap;
} seen_tracers;
static void seen_tracers_add(seen_tracers* tracker,
grpc_channel_tracer* tracer) {
if (tracker->size >= tracker->cap) {
tracker->cap = GPR_MAX(5 * sizeof(tracer), 3 * tracker->cap / 2);
tracker->tracers =
(grpc_channel_tracer**)gpr_realloc(tracker->tracers, tracker->cap);
}
tracker->tracers[tracker->size++] = tracer;
}
static bool seen_tracers_check(seen_tracers* tracker,
grpc_channel_tracer* tracer) {
for (size_t i = 0; i < tracker->size; ++i) {
if (tracker->tracers[i] == tracer) return true;
}
return false;
}
static void recursively_populate_json(grpc_channel_tracer* tracer,
seen_tracers* tracker, grpc_json* json,
bool recursive);
static void populate_node_data(grpc_trace_node* node, seen_tracers* tracker,
grpc_json* json, grpc_json* children) {
grpc_json* child = NULL;
child = grpc_json_create_child(child, json, "data",
grpc_slice_to_c_string(node->data),
GRPC_JSON_STRING, true);
if (node->error != GRPC_ERROR_NONE) {
child = grpc_json_create_child(child, json, "error",
gpr_strdup(grpc_error_string(node->error)),
GRPC_JSON_STRING, true);
}
child =
grpc_json_create_child(child, json, "time", fmt_time(node->time_created),
GRPC_JSON_STRING, true);
child = grpc_json_create_child(
child, json, "state",
grpc_connectivity_state_name(node->connectivity_state), GRPC_JSON_STRING,
false);
if (node->referenced_tracer != NULL) {
char* uuid_str;
gpr_asprintf(&uuid_str, "%ld", node->referenced_tracer->channel_uuid);
child = grpc_json_create_child(child, json, "uuid", uuid_str,
GRPC_JSON_NUMBER, true);
if (children && !seen_tracers_check(tracker, node->referenced_tracer)) {
grpc_json* referenced_tracer = grpc_json_create_child(
NULL, children, NULL, NULL, GRPC_JSON_OBJECT, false);
recursively_populate_json(node->referenced_tracer, tracker,
referenced_tracer, true);
}
}
}
static void populate_node_list_data(grpc_channel_tracer* tracer,
seen_tracers* tracker, grpc_json* nodes,
grpc_json* children) {
grpc_json* child = NULL;
grpc_trace_node* it = tracer->head_trace;
while (it != NULL) {
child = grpc_json_create_child(child, nodes, NULL, NULL, GRPC_JSON_OBJECT,
false);
populate_node_data(it, tracker, child, children);
it = it->next;
}
}
static void populate_tracer_data(grpc_channel_tracer* tracer,
seen_tracers* tracker, grpc_json* channel_data,
grpc_json* children) {
grpc_json* child = NULL;
char* uuid_str;
gpr_asprintf(&uuid_str, "%ld", tracer->channel_uuid);
child = grpc_json_create_child(child, channel_data, "uuid", uuid_str,
GRPC_JSON_NUMBER, true);
char* num_nodes_logged_str;
gpr_asprintf(&num_nodes_logged_str, "%" PRId64, tracer->num_nodes_logged);
child = grpc_json_create_child(child, channel_data, "numNodesLogged",
num_nodes_logged_str, GRPC_JSON_NUMBER, true);
child = grpc_json_create_child(child, channel_data, "startTime",
fmt_time(tracer->time_created),
GRPC_JSON_STRING, true);
child = grpc_json_create_child(child, channel_data, "nodes", NULL,
GRPC_JSON_ARRAY, false);
populate_node_list_data(tracer, tracker, child, children);
}
static void recursively_populate_json(grpc_channel_tracer* tracer,
seen_tracers* tracker, grpc_json* json,
bool recursive) {
grpc_json* channel_data = grpc_json_create_child(
NULL, json, "channelData", NULL, GRPC_JSON_OBJECT, false);
grpc_json* children = NULL;
if (recursive) {
children = grpc_json_create_child(channel_data, json, "children", NULL,
GRPC_JSON_ARRAY, false);
}
seen_tracers_add(tracker, tracer);
populate_tracer_data(tracer, tracker, channel_data, children);
}
char* grpc_channel_tracer_render_trace(grpc_channel_tracer* tracer,
bool recursive) {
grpc_json* json = grpc_json_create(GRPC_JSON_OBJECT);
seen_tracers tracker;
memset(&tracker, 0, sizeof(tracker));
recursively_populate_json(tracer, &tracker, json, recursive);
gpr_free(tracker.tracers);
char* json_str = grpc_json_dump_to_string(json, 1);
grpc_json_destroy(json);
return json_str;
}
char* grpc_channel_tracer_get_trace(intptr_t uuid, bool recursive) {
void* object;
grpc_object_registry_type type =
grpc_object_registry_get_object(uuid, &object);
GPR_ASSERT(type == GRPC_OBJECT_REGISTRY_CHANNEL ||
type == GPRC_OBJECT_REGISTRY_SUBCHANNEL);
switch (type) {
case GRPC_OBJECT_REGISTRY_CHANNEL:
return grpc_channel_get_trace(static_cast<grpc_channel*>(object),
recursive);
break;
case GPRC_OBJECT_REGISTRY_SUBCHANNEL:
return grpc_subchannel_get_trace(static_cast<grpc_subchannel*>(object),
recursive);
break;
default:
abort();
}
}

@ -0,0 +1,78 @@
/*
*
* Copyright 2017 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_CORE_LIB_CHANNEL_CHANNEL_TRACER_H
#define GRPC_CORE_LIB_CHANNEL_CHANNEL_TRACER_H
#include <grpc/grpc.h>
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/json/json.h"
/* Forward declaration */
typedef struct grpc_channel_tracer grpc_channel_tracer;
// #define GRPC_CHANNEL_TRACER_REFCOUNT_DEBUG
/* Creates a new tracer. The caller owns a reference to the returned tracer. */
#ifdef GRPC_CHANNEL_TRACER_REFCOUNT_DEBUG
grpc_channel_tracer* grpc_channel_tracer_create(size_t max_nodes, intptr_t uuid,
const char* file, int line,
const char* func);
#define GRPC_CHANNEL_TRACER_CREATE(max_nodes, id) \
grpc_channel_tracer_create(max_nodes, id, __FILE__, __LINE__, __func__)
#else
grpc_channel_tracer* grpc_channel_tracer_create(size_t max_nodes,
intptr_t uuid);
#define GRPC_CHANNEL_TRACER_CREATE(max_nodes, id) \
grpc_channel_tracer_create(max_nodes, id)
#endif
#ifdef GRPC_CHANNEL_TRACER_REFCOUNT_DEBUG
grpc_channel_tracer* grpc_channel_tracer_ref(grpc_channel_tracer* tracer,
const char* file, int line,
const char* func);
void grpc_channel_tracer_unref(grpc_channel_tracer* tracer, const char* file,
int line, const char* func);
#define GRPC_CHANNEL_TRACER_REF(tracer) \
grpc_channel_tracer_ref(tracer, __FILE__, __LINE__, __func__)
#define GRPC_CHANNEL_TRACER_UNREF(tracer) \
grpc_channel_tracer_unref(tracer, __FILE__, __LINE__, __func__)
#else
grpc_channel_tracer* grpc_channel_tracer_ref(grpc_channel_tracer* tracer);
void grpc_channel_tracer_unref(grpc_channel_tracer* tracer);
#define GRPC_CHANNEL_TRACER_REF(tracer) grpc_channel_tracer_ref(tracer)
#define GRPC_CHANNEL_TRACER_UNREF(tracer) grpc_channel_tracer_unref(tracer)
#endif
/* Adds a new trace node to the tracing object */
void grpc_channel_tracer_add_trace(grpc_channel_tracer* tracer, grpc_slice data,
grpc_error* error,
grpc_connectivity_state connectivity_state,
grpc_channel_tracer* subchannel);
/* Returns the tracing data rendered as a grpc json string.
The string is owned by the caller and must be freed. If recursive
is true, then the string will include the recursive trace for all
subtracing objects. */
char* grpc_channel_tracer_render_trace(grpc_channel_tracer* tracer,
bool recursive);
/* util functions that perform the uuid -> tracer step for you, and then
returns the trace for the uuid given. */
char* grpc_channel_tracer_get_trace(intptr_t uuid, bool recursive);
#endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_TRACER_H */

@ -19,6 +19,7 @@
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "src/core/lib/json/json.h"
@ -44,5 +45,40 @@ void grpc_json_destroy(grpc_json* json) {
json->parent->child = json->next;
}
if (json->owns_value) {
gpr_free((void*)json->value);
}
gpr_free(json);
}
grpc_json* grpc_json_link_child(grpc_json* parent, grpc_json* child,
grpc_json* sibling) {
// first child case.
if (parent->child == NULL) {
GPR_ASSERT(sibling == NULL);
parent->child = child;
return child;
}
if (sibling == NULL) {
sibling = parent->child;
}
// always find the right most sibling.
while (sibling->next != NULL) {
sibling = sibling->next;
}
sibling->next = child;
return child;
}
grpc_json* grpc_json_create_child(grpc_json* sibling, grpc_json* parent,
const char* key, const char* value,
grpc_json_type type, bool owns_value) {
grpc_json* child = grpc_json_create(type);
grpc_json_link_child(parent, child, sibling);
child->owns_value = owns_value;
child->parent = parent;
child->value = value;
child->key = key;
return child;
}

@ -19,6 +19,7 @@
#ifndef GRPC_CORE_LIB_JSON_JSON_H
#define GRPC_CORE_LIB_JSON_JSON_H
#include <stdbool.h>
#include <stdlib.h>
#include "src/core/lib/json/json_common.h"
@ -35,6 +36,9 @@ typedef struct grpc_json {
grpc_json_type type;
const char* key;
const char* value;
/* if set, destructor will free value */
bool owns_value;
} grpc_json;
/* The next two functions are going to parse the input string, and
@ -65,9 +69,24 @@ char* grpc_json_dump_to_string(grpc_json* json, int indent);
/* Use these to create or delete a grpc_json object.
* Deletion is recursive. We will not attempt to free any of the strings
* in any of the objects of that tree.
* in any of the objects of that tree, unless the boolean, owns_value,
* is true.
*/
grpc_json* grpc_json_create(grpc_json_type type);
void grpc_json_destroy(grpc_json* json);
/* Links the child json object into the parent's json tree. If the parent
* already has children, then passing in the most recently added child as the
* sibling parameter is an optimization. For if sibling is NULL, this function
* will manually traverse the tree in order to find the right most sibling.
*/
grpc_json* grpc_json_link_child(grpc_json* parent, grpc_json* child,
grpc_json* sibling);
/* Creates a child json object into the parent's json tree then links it in
* as described above. */
grpc_json* grpc_json_create_child(grpc_json* sibling, grpc_json* parent,
const char* key, const char* value,
grpc_json_type type, bool owns_value);
#endif /* GRPC_CORE_LIB_JSON_JSON_H */

@ -0,0 +1,100 @@
/*
*
* Copyright 2017 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/support/object_registry.h"
#include <grpc/support/alloc.h>
#include <grpc/support/avl.h>
#include <grpc/support/log.h>
// file global lock and avl.
static gpr_mu g_mu;
static gpr_avl g_avl;
static intptr_t g_uuid = 0;
typedef struct {
void* object;
grpc_object_registry_type type;
} object_tracker;
// avl vtable for uuid (intptr_t) -> object_tracker
// this table is only looking, it does not own anything.
static void destroy_intptr(void* not_used, void* user_data) {}
static void* copy_intptr(void* key, void* user_data) { return key; }
static long compare_intptr(void* key1, void* key2, void* user_data) {
return key1 > key2;
}
static void destroy_tracker(void* tracker, void* user_data) {
gpr_free((object_tracker*)tracker);
}
static void* copy_tracker(void* value, void* user_data) {
object_tracker* old = static_cast<object_tracker*>(value);
object_tracker* new_obj =
static_cast<object_tracker*>(gpr_malloc(sizeof(object_tracker)));
new_obj->object = old->object;
new_obj->type = old->type;
return new_obj;
}
static const gpr_avl_vtable avl_vtable = {
destroy_intptr, copy_intptr, compare_intptr, destroy_tracker, copy_tracker};
void grpc_object_registry_init() {
gpr_mu_init(&g_mu);
g_avl = gpr_avl_create(&avl_vtable);
}
void grpc_object_registry_shutdown() {
gpr_avl_unref(g_avl, nullptr);
gpr_mu_destroy(&g_mu);
}
intptr_t grpc_object_registry_register_object(void* object,
grpc_object_registry_type type) {
object_tracker* tracker =
static_cast<object_tracker*>(gpr_malloc(sizeof(object_tracker)));
tracker->object = object;
tracker->type = type;
intptr_t prior = gpr_atm_no_barrier_fetch_add(&g_uuid, 1);
gpr_mu_lock(&g_mu);
g_avl = gpr_avl_add(g_avl, (void*)prior, tracker, NULL);
gpr_mu_unlock(&g_mu);
return prior;
}
void grpc_object_registry_unregister_object(intptr_t uuid) {
gpr_mu_lock(&g_mu);
g_avl = gpr_avl_remove(g_avl, (void*)uuid, nullptr);
gpr_mu_unlock(&g_mu);
}
grpc_object_registry_type grpc_object_registry_get_object(intptr_t uuid,
void** object) {
GPR_ASSERT(object);
gpr_mu_lock(&g_mu);
object_tracker* tracker =
static_cast<object_tracker*>(gpr_avl_get(g_avl, (void*)uuid, nullptr));
gpr_mu_unlock(&g_mu);
if (tracker == NULL) {
*object = NULL;
return GRPC_OBJECT_REGISTRY_UNKNOWN;
}
*object = tracker->object;
return tracker->type;
}

@ -0,0 +1,39 @@
/*
*
* Copyright 2017 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_CORE_LIB_SUPPORT_OBJECT_REGISTRY_H
#define GRPC_CORE_LIB_SUPPORT_OBJECT_REGISTRY_H
#include <stdint.h>
typedef enum {
GRPC_OBJECT_REGISTRY_CHANNEL,
GPRC_OBJECT_REGISTRY_SUBCHANNEL,
GRPC_OBJECT_REGISTRY_UNKNOWN,
} grpc_object_registry_type;
void grpc_object_registry_init();
void grpc_object_registry_shutdown();
intptr_t grpc_object_registry_register_object(void* object,
grpc_object_registry_type type);
void grpc_object_registry_unregister_object(intptr_t uuid);
grpc_object_registry_type grpc_object_registry_get_object(intptr_t uuid,
void** object);
#endif /* GRPC_CORE_LIB_SUPPORT_OBJECT_REGISTRY_H */

@ -28,9 +28,11 @@
#include <grpc/support/string_util.h>
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_tracer.h"
#include "src/core/lib/debug/stats.h"
#include "src/core/lib/iomgr/iomgr.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/support/object_registry.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/surface/call.h"
@ -51,6 +53,7 @@ typedef struct registered_call {
} registered_call;
struct grpc_channel {
intptr_t uuid;
int is_client;
grpc_compression_options compression_options;
grpc_mdelem default_authority;
@ -60,6 +63,8 @@ struct grpc_channel {
gpr_mu registered_call_mu;
registered_call* registered_calls;
grpc_channel_tracer* tracer;
char* target;
};
@ -91,12 +96,16 @@ grpc_channel* grpc_channel_create_with_builder(
grpc_error_string(error));
GRPC_ERROR_UNREF(error);
gpr_free(target);
goto done;
grpc_channel_args_destroy(args);
return channel;
}
memset(channel, 0, sizeof(*channel));
channel->uuid = grpc_object_registry_register_object(
channel, GRPC_OBJECT_REGISTRY_CHANNEL);
channel->target = target;
channel->is_client = grpc_channel_stack_type_is_client(channel_stack_type);
channel->tracer = NULL;
gpr_mu_init(&channel->registered_call_mu);
channel->registered_calls = nullptr;
@ -186,14 +195,34 @@ grpc_channel* grpc_channel_create_with_builder(
.enabled_stream_compression_algorithms_bitset =
(uint32_t)args->args[i].value.integer |
0x1; /* always support no compression */
} else if (0 ==
strcmp(args->args[i].key, GRPC_ARG_CHANNEL_TRACING_MAX_NODES)) {
GPR_ASSERT(channel->tracer == NULL);
// max_nodes defaults to 10, clamped between 0 and 100.
const grpc_integer_options options = {10, 0, 100};
size_t max_nodes =
(size_t)grpc_channel_arg_get_integer(&args->args[i], options);
if (max_nodes > 0) {
channel->tracer = GRPC_CHANNEL_TRACER_CREATE(max_nodes, channel->uuid);
}
}
}
done:
grpc_channel_args_destroy(args);
grpc_channel_tracer_add_trace(
channel->tracer, grpc_slice_from_static_string("Channel created"),
GRPC_ERROR_NONE, GRPC_CHANNEL_IDLE, NULL);
return channel;
}
char* grpc_channel_get_trace(grpc_channel* channel, bool recursive) {
return channel->tracer
? grpc_channel_tracer_render_trace(channel->tracer, recursive)
: NULL;
}
intptr_t grpc_channel_get_uuid(grpc_channel* channel) { return channel->uuid; }
grpc_channel* grpc_channel_create(const char* target,
const grpc_channel_args* input_args,
grpc_channel_stack_type channel_stack_type,

@ -58,6 +58,9 @@ grpc_mdelem grpc_channel_get_reffed_status_elem(grpc_channel* channel,
size_t grpc_channel_get_call_size_estimate(grpc_channel* channel);
void grpc_channel_update_call_size_estimate(grpc_channel* channel, size_t size);
char* grpc_channel_get_trace(grpc_channel* channel, bool recursive);
intptr_t grpc_channel_get_uuid(grpc_channel* channel);
#ifndef NDEBUG
void grpc_channel_internal_ref(grpc_channel* channel, const char* reason);
void grpc_channel_internal_unref(grpc_channel* channel, const char* reason);

@ -41,6 +41,7 @@
#include "src/core/lib/profiling/timers.h"
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/support/fork.h"
#include "src/core/lib/support/object_registry.h"
#include "src/core/lib/support/thd_internal.h"
#include "src/core/lib/surface/alarm_internal.h"
#include "src/core/lib/surface/api_trace.h"
@ -129,6 +130,7 @@ void grpc_init(void) {
grpc_slice_intern_init();
grpc_mdctx_global_init();
grpc_channel_init_init();
grpc_object_registry_init();
grpc_security_pre_init();
grpc_core::ExecCtx::GlobalInit();
grpc_iomgr_init();
@ -177,6 +179,7 @@ void grpc_shutdown(void) {
grpc_mdctx_global_shutdown();
grpc_handshaker_factory_registry_shutdown();
grpc_slice_intern_shutdown();
grpc_object_registry_shutdown();
grpc_stats_shutdown();
}
grpc_core::ExecCtx::GlobalShutdown();

@ -38,6 +38,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/support/log_windows.cc',
'src/core/lib/support/mpscq.cc',
'src/core/lib/support/murmur_hash.cc',
'src/core/lib/support/object_registry.cc',
'src/core/lib/support/string.cc',
'src/core/lib/support/string_posix.cc',
'src/core/lib/support/string_util_windows.cc',
@ -64,6 +65,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/channel/channel_args.cc',
'src/core/lib/channel/channel_stack.cc',
'src/core/lib/channel/channel_stack_builder.cc',
'src/core/lib/channel/channel_tracer.cc',
'src/core/lib/channel/connected_channel.cc',
'src/core/lib/channel/handshaker.cc',
'src/core/lib/channel/handshaker_factory.cc',

@ -0,0 +1,210 @@
/*
*
* Copyright 2017 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 <stdlib.h>
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/useful.h>
#include "src/core/lib/channel/channel_tracer.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "test/core/util/channel_tracing_utils.h"
#include "test/core/util/test_config.h"
static void add_simple_trace(grpc_channel_tracer* tracer) {
grpc_channel_tracer_add_trace(
tracer, grpc_slice_from_static_string("simple trace"),
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), GRPC_CHANNEL_READY, NULL);
}
// checks for the existence of all the required members of the tracer.
static void validate_tracer(grpc_channel_tracer* tracer,
size_t expected_num_nodes_logged,
size_t max_nodes) {
char* json_str = grpc_channel_tracer_render_trace(tracer, true);
grpc_json* json = grpc_json_parse_string(json_str);
validate_channel_data(json, expected_num_nodes_logged,
GPR_MIN(expected_num_nodes_logged, max_nodes));
grpc_json_destroy(json);
gpr_free(json_str);
}
// ensures the tracer has the correct number of children tracers.
static void validate_children(grpc_channel_tracer* tracer,
size_t expected_num_children) {
char* json_str = grpc_channel_tracer_render_trace(tracer, true);
grpc_json* json = grpc_json_parse_string(json_str);
validate_json_array_size(json, "children", expected_num_children);
grpc_json_destroy(json);
gpr_free(json_str);
}
static intptr_t uuid = 0;
static void test_basic_channel_tracing(size_t max_nodes) {
grpc_channel_tracer* tracer = GRPC_CHANNEL_TRACER_CREATE(max_nodes, uuid++);
grpc_core::ExecCtx exec_ctx;
add_simple_trace(tracer);
add_simple_trace(tracer);
grpc_channel_tracer_add_trace(
tracer, grpc_slice_from_static_string("trace three"),
grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"),
GRPC_ERROR_INT_HTTP2_ERROR, 2),
GRPC_CHANNEL_IDLE, NULL);
grpc_channel_tracer_add_trace(tracer,
grpc_slice_from_static_string("trace four"),
GRPC_ERROR_NONE, GRPC_CHANNEL_SHUTDOWN, NULL);
validate_tracer(tracer, 4, max_nodes);
add_simple_trace(tracer);
add_simple_trace(tracer);
validate_tracer(tracer, 6, max_nodes);
add_simple_trace(tracer);
add_simple_trace(tracer);
add_simple_trace(tracer);
add_simple_trace(tracer);
validate_tracer(tracer, 10, max_nodes);
GRPC_CHANNEL_TRACER_UNREF(tracer);
}
static void test_basic_channel_sizing() {
test_basic_channel_tracing(0);
test_basic_channel_tracing(1);
test_basic_channel_tracing(2);
test_basic_channel_tracing(6);
test_basic_channel_tracing(10);
test_basic_channel_tracing(15);
}
static void test_complex_channel_tracing(size_t max_nodes) {
grpc_channel_tracer* tracer = GRPC_CHANNEL_TRACER_CREATE(max_nodes, uuid++);
grpc_core::ExecCtx exec_ctx;
add_simple_trace(tracer);
add_simple_trace(tracer);
grpc_channel_tracer* sc1 = GRPC_CHANNEL_TRACER_CREATE(max_nodes, uuid++);
grpc_channel_tracer_add_trace(
tracer, grpc_slice_from_static_string("subchannel one created"),
GRPC_ERROR_NONE, GRPC_CHANNEL_IDLE, sc1);
validate_tracer(tracer, 3, max_nodes);
add_simple_trace(sc1);
add_simple_trace(sc1);
add_simple_trace(sc1);
validate_tracer(sc1, 3, max_nodes);
add_simple_trace(sc1);
add_simple_trace(sc1);
add_simple_trace(sc1);
validate_tracer(sc1, 6, max_nodes);
add_simple_trace(tracer);
add_simple_trace(tracer);
validate_tracer(tracer, 5, max_nodes);
grpc_channel_tracer* sc2 = GRPC_CHANNEL_TRACER_CREATE(max_nodes, uuid++);
grpc_channel_tracer_add_trace(
tracer, grpc_slice_from_static_string("subchannel two created"),
GRPC_ERROR_NONE, GRPC_CHANNEL_IDLE, sc2);
grpc_channel_tracer_add_trace(
tracer, grpc_slice_from_static_string("subchannel one inactive"),
GRPC_ERROR_NONE, GRPC_CHANNEL_IDLE, sc1);
validate_tracer(tracer, 7, max_nodes);
add_simple_trace(tracer);
add_simple_trace(tracer);
add_simple_trace(tracer);
add_simple_trace(tracer);
add_simple_trace(tracer);
add_simple_trace(tracer);
GRPC_CHANNEL_TRACER_UNREF(sc1);
GRPC_CHANNEL_TRACER_UNREF(sc2);
GRPC_CHANNEL_TRACER_UNREF(tracer);
}
static void test_complex_channel_sizing() {
test_complex_channel_tracing(0);
test_complex_channel_tracing(1);
test_complex_channel_tracing(2);
test_complex_channel_tracing(6);
test_complex_channel_tracing(10);
test_complex_channel_tracing(15);
}
static void test_delete_parent_first() {
grpc_channel_tracer* tracer = GRPC_CHANNEL_TRACER_CREATE(3, uuid++);
grpc_core::ExecCtx exec_ctx;
add_simple_trace(tracer);
add_simple_trace(tracer);
grpc_channel_tracer* sc1 = GRPC_CHANNEL_TRACER_CREATE(3, uuid++);
grpc_channel_tracer_add_trace(
tracer, grpc_slice_from_static_string("subchannel one created"),
GRPC_ERROR_NONE, GRPC_CHANNEL_IDLE, sc1);
// this will cause the tracer destructor to run.
GRPC_CHANNEL_TRACER_UNREF(tracer);
GRPC_CHANNEL_TRACER_UNREF(sc1);
}
static void test_nesting() {
grpc_channel_tracer* tracer = GRPC_CHANNEL_TRACER_CREATE(10, uuid++);
grpc_core::ExecCtx exec_ctx;
add_simple_trace(tracer);
add_simple_trace(tracer);
grpc_channel_tracer* sc1 = GRPC_CHANNEL_TRACER_CREATE(5, uuid++);
grpc_channel_tracer_add_trace(
tracer, grpc_slice_from_static_string("subchannel one created"),
GRPC_ERROR_NONE, GRPC_CHANNEL_IDLE, sc1);
// channel has only one subchannel right here.
validate_children(tracer, 1);
add_simple_trace(sc1);
grpc_channel_tracer* conn1 = GRPC_CHANNEL_TRACER_CREATE(5, uuid++);
// nesting one level deeper.
grpc_channel_tracer_add_trace(
sc1, grpc_slice_from_static_string("connection one created"),
GRPC_ERROR_NONE, GRPC_CHANNEL_IDLE, conn1);
validate_children(sc1, 1);
add_simple_trace(conn1);
add_simple_trace(tracer);
add_simple_trace(tracer);
grpc_channel_tracer* sc2 = GRPC_CHANNEL_TRACER_CREATE(5, uuid++);
grpc_channel_tracer_add_trace(
tracer, grpc_slice_from_static_string("subchannel two created"),
GRPC_ERROR_NONE, GRPC_CHANNEL_IDLE, sc2);
validate_children(tracer, 2);
// this trace should not get added to the parents children since it is already
// present in the tracer.
grpc_channel_tracer_add_trace(
tracer, grpc_slice_from_static_string("subchannel one inactive"),
GRPC_ERROR_NONE, GRPC_CHANNEL_IDLE, sc1);
validate_children(tracer, 2);
add_simple_trace(tracer);
GRPC_CHANNEL_TRACER_UNREF(conn1);
GRPC_CHANNEL_TRACER_UNREF(sc1);
GRPC_CHANNEL_TRACER_UNREF(sc2);
GRPC_CHANNEL_TRACER_UNREF(tracer);
}
int main(int argc, char** argv) {
grpc_test_init(argc, argv);
grpc_init();
test_basic_channel_tracing(5);
test_basic_channel_sizing();
test_complex_channel_tracing(5);
test_complex_channel_sizing();
test_delete_parent_first();
test_nesting();
grpc_shutdown();
return 0;
}

@ -0,0 +1,60 @@
/*
*
* Copyright 2017 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 <stdlib.h>
#include <string.h>
#include <grpc/support/log.h>
#include <grpc/support/useful.h>
#include "src/core/lib/channel/channel_tracer.h"
#include "src/core/lib/json/json.h"
static grpc_json* get_json_child(grpc_json* parent, const char* key) {
GPR_ASSERT(parent != NULL);
for (grpc_json* child = parent->child; child != NULL; child = child->next) {
if (child->key != NULL && strcmp(child->key, key) == 0) return child;
}
return NULL;
}
void validate_json_array_size(grpc_json* json, const char* key,
size_t expected_size) {
grpc_json* arr = get_json_child(json, key);
GPR_ASSERT(arr);
GPR_ASSERT(arr->type == GRPC_JSON_ARRAY);
size_t count = 0;
for (grpc_json* child = arr->child; child != NULL; child = child->next) {
++count;
}
GPR_ASSERT(count == expected_size);
}
void validate_channel_data(grpc_json* json, size_t num_nodes_logged_expected,
size_t actual_num_nodes_expected) {
GPR_ASSERT(json);
grpc_json* channel_data = get_json_child(json, "channelData");
grpc_json* num_nodes_logged_json =
get_json_child(channel_data, "numNodesLogged");
GPR_ASSERT(num_nodes_logged_json);
grpc_json* start_time = get_json_child(channel_data, "startTime");
GPR_ASSERT(start_time);
size_t num_nodes_logged =
(size_t)strtol(num_nodes_logged_json->value, NULL, 0);
GPR_ASSERT(num_nodes_logged == num_nodes_logged_expected);
validate_json_array_size(channel_data, "nodes", actual_num_nodes_expected);
}

@ -0,0 +1,30 @@
/*
*
* Copyright 2017 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_TEST_CORE_UTIL_CHANNEL_TRACING_UTILS_H
#define GRPC_TEST_CORE_UTIL_CHANNEL_TRACING_UTILS_H
#include "src/core/lib/channel/channel_tracer.h"
void validate_json_array_size(grpc_json* json, const char* key,
size_t expected_size);
void validate_channel_data(grpc_json* json, size_t num_nodes_logged_expected,
size_t actual_num_nodes_expected);
#endif /* GRPC_TEST_CORE_UTIL_CHANNEL_TRACING_UTILS_H */

@ -938,6 +938,7 @@ src/core/lib/backoff/backoff.h \
src/core/lib/channel/channel_args.h \
src/core/lib/channel/channel_stack.h \
src/core/lib/channel/channel_stack_builder.h \
src/core/lib/channel/channel_tracer.h \
src/core/lib/channel/connected_channel.h \
src/core/lib/channel/context.h \
src/core/lib/channel/handshaker.h \
@ -1039,6 +1040,7 @@ src/core/lib/support/manual_constructor.h \
src/core/lib/support/memory.h \
src/core/lib/support/mpscq.h \
src/core/lib/support/murmur_hash.h \
src/core/lib/support/object_registry.h \
src/core/lib/support/ref_counted.h \
src/core/lib/support/ref_counted_ptr.h \
src/core/lib/support/spinlock.h \

@ -1040,6 +1040,8 @@ src/core/lib/channel/channel_stack.cc \
src/core/lib/channel/channel_stack.h \
src/core/lib/channel/channel_stack_builder.cc \
src/core/lib/channel/channel_stack_builder.h \
src/core/lib/channel/channel_tracer.cc \
src/core/lib/channel/channel_tracer.h \
src/core/lib/channel/connected_channel.cc \
src/core/lib/channel/connected_channel.h \
src/core/lib/channel/context.h \
@ -1305,6 +1307,8 @@ src/core/lib/support/mpscq.cc \
src/core/lib/support/mpscq.h \
src/core/lib/support/murmur_hash.cc \
src/core/lib/support/murmur_hash.h \
src/core/lib/support/object_registry.cc \
src/core/lib/support/object_registry.h \
src/core/lib/support/ref_counted.h \
src/core/lib/support/ref_counted_ptr.h \
src/core/lib/support/spinlock.h \

@ -914,6 +914,23 @@
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
"gpr_test_util",
"grpc",
"grpc_test_util"
],
"headers": [],
"is_filegroup": false,
"language": "c",
"name": "grpc_channel_tracer_test",
"src": [
"test/core/channel/channel_tracer_test.cc"
],
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
@ -7791,6 +7808,7 @@
"src/core/lib/support/log_windows.cc",
"src/core/lib/support/mpscq.cc",
"src/core/lib/support/murmur_hash.cc",
"src/core/lib/support/object_registry.cc",
"src/core/lib/support/string.cc",
"src/core/lib/support/string_posix.cc",
"src/core/lib/support/string_util_windows.cc",
@ -7859,6 +7877,7 @@
"src/core/lib/support/memory.h",
"src/core/lib/support/mpscq.h",
"src/core/lib/support/murmur_hash.h",
"src/core/lib/support/object_registry.h",
"src/core/lib/support/spinlock.h",
"src/core/lib/support/string.h",
"src/core/lib/support/string_windows.h",
@ -7908,6 +7927,7 @@
"src/core/lib/support/memory.h",
"src/core/lib/support/mpscq.h",
"src/core/lib/support/murmur_hash.h",
"src/core/lib/support/object_registry.h",
"src/core/lib/support/spinlock.h",
"src/core/lib/support/string.h",
"src/core/lib/support/string_windows.h",
@ -8002,6 +8022,7 @@
"src/core/lib/channel/channel_args.cc",
"src/core/lib/channel/channel_stack.cc",
"src/core/lib/channel/channel_stack_builder.cc",
"src/core/lib/channel/channel_tracer.cc",
"src/core/lib/channel/connected_channel.cc",
"src/core/lib/channel/handshaker.cc",
"src/core/lib/channel/handshaker_factory.cc",
@ -8158,6 +8179,7 @@
"src/core/lib/channel/channel_args.h",
"src/core/lib/channel/channel_stack.h",
"src/core/lib/channel/channel_stack_builder.h",
"src/core/lib/channel/channel_tracer.h",
"src/core/lib/channel/connected_channel.h",
"src/core/lib/channel/context.h",
"src/core/lib/channel/handshaker.h",
@ -8297,6 +8319,7 @@
"src/core/lib/channel/channel_args.h",
"src/core/lib/channel/channel_stack.h",
"src/core/lib/channel/channel_stack_builder.h",
"src/core/lib/channel/channel_tracer.h",
"src/core/lib/channel/connected_channel.h",
"src/core/lib/channel/context.h",
"src/core/lib/channel/handshaker.h",
@ -8940,6 +8963,7 @@
"test/core/end2end/fixtures/http_proxy_fixture.h",
"test/core/end2end/fixtures/proxy.h",
"test/core/iomgr/endpoint_tests.h",
"test/core/util/channel_tracing_utils.h",
"test/core/util/debugger_macros.h",
"test/core/util/grpc_profiler.h",
"test/core/util/histogram.h",
@ -8967,6 +8991,8 @@
"test/core/end2end/fixtures/proxy.h",
"test/core/iomgr/endpoint_tests.cc",
"test/core/iomgr/endpoint_tests.h",
"test/core/util/channel_tracing_utils.cc",
"test/core/util/channel_tracing_utils.h",
"test/core/util/debugger_macros.cc",
"test/core/util/debugger_macros.h",
"test/core/util/grpc_profiler.cc",

@ -1223,6 +1223,30 @@
],
"uses_polling": false
},
{
"args": [],
"benchmark": false,
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": false,
"language": "c",
"name": "grpc_channel_tracer_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": false
},
{
"args": [],
"benchmark": false,

Loading…
Cancel
Save