diff options
Diffstat (limited to 'src/core/lib')
-rw-r--r-- | src/core/lib/debug/stats.c | 67 | ||||
-rw-r--r-- | src/core/lib/debug/stats.h | 44 | ||||
-rw-r--r-- | src/core/lib/debug/stats_data.c | 25 | ||||
-rw-r--r-- | src/core/lib/debug/stats_data.h | 47 | ||||
-rw-r--r-- | src/core/lib/debug/stats_data.yaml | 9 | ||||
-rw-r--r-- | src/core/lib/iomgr/ev_epoll1_linux.c | 2 | ||||
-rw-r--r-- | src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c | 8 | ||||
-rw-r--r-- | src/core/lib/iomgr/ev_epoll_thread_pool_linux.c | 2 | ||||
-rw-r--r-- | src/core/lib/iomgr/ev_epollex_linux.c | 2 | ||||
-rw-r--r-- | src/core/lib/iomgr/ev_epollsig_linux.c | 2 | ||||
-rw-r--r-- | src/core/lib/iomgr/ev_poll_posix.c | 2 | ||||
-rw-r--r-- | src/core/lib/iomgr/exec_ctx.h | 7 | ||||
-rw-r--r-- | src/core/lib/iomgr/iocp_windows.c | 2 | ||||
-rw-r--r-- | src/core/lib/iomgr/tcp_posix.c | 10 | ||||
-rw-r--r-- | src/core/lib/surface/call.c | 6 | ||||
-rw-r--r-- | src/core/lib/surface/init.c | 3 |
16 files changed, 232 insertions, 6 deletions
diff --git a/src/core/lib/debug/stats.c b/src/core/lib/debug/stats.c new file mode 100644 index 0000000000..4dbd94c724 --- /dev/null +++ b/src/core/lib/debug/stats.c @@ -0,0 +1,67 @@ +/* + * + * 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/debug/stats.h" + +#include <inttypes.h> +#include <string.h> + +#include <grpc/support/alloc.h> +#include <grpc/support/string_util.h> +#include <grpc/support/useful.h> + +#include "src/core/lib/support/string.h" + +grpc_stats_data *grpc_stats_per_cpu_storage = NULL; +static size_t g_num_cores; + +void grpc_stats_init(void) { + g_num_cores = GPR_MAX(1, gpr_cpu_num_cores()); + grpc_stats_per_cpu_storage = + gpr_zalloc(sizeof(grpc_stats_data) * g_num_cores); +} + +void grpc_stats_shutdown(void) { gpr_free(grpc_stats_per_cpu_storage); } + +void grpc_stats_collect(grpc_stats_data *output) { + memset(output, 0, sizeof(*output)); + for (size_t core = 0; core < g_num_cores; core++) { + for (size_t i = 0; i < GRPC_STATS_COUNTER_COUNT; i++) { + output->counters[i] += gpr_atm_no_barrier_load( + &grpc_stats_per_cpu_storage[core].counters[i]); + } + } +} + +char *grpc_stats_data_as_json(const grpc_stats_data *data) { + gpr_strvec v; + char *tmp; + bool is_first = true; + gpr_strvec_init(&v); + gpr_strvec_add(&v, gpr_strdup("{")); + for (size_t i = 0; i < GRPC_STATS_COUNTER_COUNT; i++) { + gpr_asprintf(&tmp, "%s\"%s\": %" PRIdPTR, is_first ? "" : ", ", + grpc_stats_counter_name[i], data->counters[i]); + gpr_strvec_add(&v, tmp); + is_first = false; + } + gpr_strvec_add(&v, gpr_strdup("}")); + tmp = gpr_strvec_flatten(&v, NULL); + gpr_strvec_destroy(&v); + return tmp; +} diff --git a/src/core/lib/debug/stats.h b/src/core/lib/debug/stats.h new file mode 100644 index 0000000000..563b108dff --- /dev/null +++ b/src/core/lib/debug/stats.h @@ -0,0 +1,44 @@ +/* + * + * 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_DEBUG_STATS_H +#define GRPC_CORE_LIB_DEBUG_STATS_H + +#include <grpc/support/atm.h> +#include "src/core/lib/debug/stats_data.h" +#include "src/core/lib/iomgr/exec_ctx.h" + +typedef struct grpc_stats_data { + gpr_atm counters[GRPC_STATS_COUNTER_COUNT]; +} grpc_stats_data; + +extern grpc_stats_data *grpc_stats_per_cpu_storage; + +#define GRPC_THREAD_STATS_DATA(exec_ctx) \ + (&grpc_stats_per_cpu_storage[(exec_ctx)->starting_cpu]) + +#define GRPC_STATS_INC_COUNTER(exec_ctx, ctr) \ + (gpr_atm_no_barrier_fetch_add( \ + &GRPC_THREAD_STATS_DATA((exec_ctx))->counters[(ctr)], 1)) + +void grpc_stats_init(void); +void grpc_stats_shutdown(void); +void grpc_stats_collect(grpc_stats_data *output); +char *grpc_stats_data_as_json(const grpc_stats_data *data); + +#endif diff --git a/src/core/lib/debug/stats_data.c b/src/core/lib/debug/stats_data.c new file mode 100644 index 0000000000..2203358a7e --- /dev/null +++ b/src/core/lib/debug/stats_data.c @@ -0,0 +1,25 @@ +/* + * 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. + */ + +/* + * Automatically generated by tools/codegen/core/gen_stats_data.py + */ + +#include "src/core/lib/debug/stats_data.h" +const char *grpc_stats_counter_name[GRPC_STATS_COUNTER_COUNT] = { + "client_calls_created", "server_calls_created", "syscall_write", + "syscall_read", "syscall_poll", "syscall_wait", +}; diff --git a/src/core/lib/debug/stats_data.h b/src/core/lib/debug/stats_data.h new file mode 100644 index 0000000000..c9c2f65c30 --- /dev/null +++ b/src/core/lib/debug/stats_data.h @@ -0,0 +1,47 @@ +/* + * 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. + */ + +/* + * Automatically generated by tools/codegen/core/gen_stats_data.py + */ + +#ifndef GRPC_CORE_LIB_DEBUG_STATS_DATA_H +#define GRPC_CORE_LIB_DEBUG_STATS_DATA_H + +typedef enum { + GRPC_STATS_COUNTER_CLIENT_CALLS_CREATED, + GRPC_STATS_COUNTER_SERVER_CALLS_CREATED, + GRPC_STATS_COUNTER_SYSCALL_WRITE, + GRPC_STATS_COUNTER_SYSCALL_READ, + GRPC_STATS_COUNTER_SYSCALL_POLL, + GRPC_STATS_COUNTER_SYSCALL_WAIT, + GRPC_STATS_COUNTER_COUNT +} grpc_stats_counters; +#define GRPC_STATS_INC_CLIENT_CALLS_CREATED(exec_ctx) \ + GRPC_STATS_INC_COUNTER((exec_ctx), GRPC_STATS_COUNTER_CLIENT_CALLS_CREATED) +#define GRPC_STATS_INC_SERVER_CALLS_CREATED(exec_ctx) \ + GRPC_STATS_INC_COUNTER((exec_ctx), GRPC_STATS_COUNTER_SERVER_CALLS_CREATED) +#define GRPC_STATS_INC_SYSCALL_WRITE(exec_ctx) \ + GRPC_STATS_INC_COUNTER((exec_ctx), GRPC_STATS_COUNTER_SYSCALL_WRITE) +#define GRPC_STATS_INC_SYSCALL_READ(exec_ctx) \ + GRPC_STATS_INC_COUNTER((exec_ctx), GRPC_STATS_COUNTER_SYSCALL_READ) +#define GRPC_STATS_INC_SYSCALL_POLL(exec_ctx) \ + GRPC_STATS_INC_COUNTER((exec_ctx), GRPC_STATS_COUNTER_SYSCALL_POLL) +#define GRPC_STATS_INC_SYSCALL_WAIT(exec_ctx) \ + GRPC_STATS_INC_COUNTER((exec_ctx), GRPC_STATS_COUNTER_SYSCALL_WAIT) +extern const char *grpc_stats_counter_name[GRPC_STATS_COUNTER_COUNT]; + +#endif /* GRPC_CORE_LIB_DEBUG_STATS_DATA_H */ diff --git a/src/core/lib/debug/stats_data.yaml b/src/core/lib/debug/stats_data.yaml new file mode 100644 index 0000000000..8afe48f5cd --- /dev/null +++ b/src/core/lib/debug/stats_data.yaml @@ -0,0 +1,9 @@ +# Stats data declaration +# use tools/codegen/core/gen_stats_data.py to turn this into stats_data.h + +- counter: client_calls_created +- counter: server_calls_created +- counter: syscall_write +- counter: syscall_read +- counter: syscall_poll +- counter: syscall_wait diff --git a/src/core/lib/iomgr/ev_epoll1_linux.c b/src/core/lib/iomgr/ev_epoll1_linux.c index 8b0a65006e..7f053fa728 100644 --- a/src/core/lib/iomgr/ev_epoll1_linux.c +++ b/src/core/lib/iomgr/ev_epoll1_linux.c @@ -39,6 +39,7 @@ #include <grpc/support/tls.h> #include <grpc/support/useful.h> +#include "src/core/lib/debug/stats.h" #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/lockfree_event.h" @@ -635,6 +636,7 @@ static grpc_error *do_epoll_wait(grpc_exec_ctx *exec_ctx, grpc_pollset *ps, GRPC_SCHEDULING_START_BLOCKING_REGION; } do { + GRPC_STATS_INC_SYSCALL_POLL(exec_ctx); r = epoll_wait(g_epoll_set.epfd, g_epoll_set.events, MAX_EPOLL_EVENTS, timeout); } while (r < 0 && errno == EINTR); diff --git a/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c b/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c index f2f3e15704..e2e3cd9003 100644 --- a/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c +++ b/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c @@ -40,6 +40,7 @@ #include <grpc/support/tls.h> #include <grpc/support/useful.h> +#include "src/core/lib/debug/stats.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/iomgr_internal.h" @@ -1286,7 +1287,8 @@ static void pollset_destroy(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) { } /* NOTE: This function may modify 'now' */ -static bool acquire_polling_lease(grpc_pollset_worker *worker, +static bool acquire_polling_lease(grpc_exec_ctx *exec_ctx, + grpc_pollset_worker *worker, polling_island *pi, gpr_timespec deadline, gpr_timespec *now) { bool is_lease_acquired = false; @@ -1306,6 +1308,7 @@ static bool acquire_polling_lease(grpc_pollset_worker *worker, } else { struct timespec sigwait_timeout = millis_to_timespec(timeout_ms); GRPC_SCHEDULING_START_BLOCKING_REGION; + GRPC_STATS_INC_SYSCALL_WAIT(exec_ctx); ret = sigtimedwait(&g_wakeup_sig_set, NULL, &sigwait_timeout); GRPC_SCHEDULING_END_BLOCKING_REGION; } @@ -1378,7 +1381,7 @@ static void pollset_do_epoll_pwait(grpc_exec_ctx *exec_ctx, int epoll_fd, sigset_t *sig_mask, grpc_error **error) { /* Only g_max_pollers_per_pi threads can be doing polling in parallel. If we cannot get a lease, we cannot continue to do epoll_pwait() */ - if (!acquire_polling_lease(worker, pi, deadline, &now)) { + if (!acquire_polling_lease(exec_ctx, worker, pi, deadline, &now)) { return; } @@ -1391,6 +1394,7 @@ static void pollset_do_epoll_pwait(grpc_exec_ctx *exec_ctx, int epoll_fd, int timeout_ms = poll_deadline_to_millis_timeout(deadline, now); GRPC_SCHEDULING_START_BLOCKING_REGION; + GRPC_STATS_INC_SYSCALL_POLL(exec_ctx); ep_rv = epoll_pwait(epoll_fd, ep_ev, GRPC_EPOLL_MAX_EVENTS, timeout_ms, sig_mask); GRPC_SCHEDULING_END_BLOCKING_REGION; diff --git a/src/core/lib/iomgr/ev_epoll_thread_pool_linux.c b/src/core/lib/iomgr/ev_epoll_thread_pool_linux.c index 07c8eadf4f..ddb8c74d2d 100644 --- a/src/core/lib/iomgr/ev_epoll_thread_pool_linux.c +++ b/src/core/lib/iomgr/ev_epoll_thread_pool_linux.c @@ -41,6 +41,7 @@ #include <grpc/support/tls.h> #include <grpc/support/useful.h> +#include "src/core/lib/debug/stats.h" #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/lockfree_event.h" @@ -776,6 +777,7 @@ static void do_epoll_wait(grpc_exec_ctx *exec_ctx, int epoll_fd, epoll_set *eps, GRPC_SCHEDULING_START_BLOCKING_REGION; acquire_epoll_lease(eps); + GRPC_STATS_INC_SYSCALL_POLL(exec_ctx); ep_rv = epoll_wait(epoll_fd, ep_ev, GRPC_EPOLL_MAX_EVENTS, timeout_ms); release_epoll_lease(eps); GRPC_SCHEDULING_END_BLOCKING_REGION; diff --git a/src/core/lib/iomgr/ev_epollex_linux.c b/src/core/lib/iomgr/ev_epollex_linux.c index 1f4adea5d4..0e42f76af3 100644 --- a/src/core/lib/iomgr/ev_epollex_linux.c +++ b/src/core/lib/iomgr/ev_epollex_linux.c @@ -37,6 +37,7 @@ #include <grpc/support/tls.h> #include <grpc/support/useful.h> +#include "src/core/lib/debug/stats.h" #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/is_epollexclusive_available.h" @@ -814,6 +815,7 @@ static grpc_error *pollset_epoll(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, } int r; do { + GRPC_STATS_INC_SYSCALL_POLL(exec_ctx); r = epoll_wait(p->epfd, pollset->events, MAX_EPOLL_EVENTS, timeout); } while (r < 0 && errno == EINTR); if (timeout != 0) { diff --git a/src/core/lib/iomgr/ev_epollsig_linux.c b/src/core/lib/iomgr/ev_epollsig_linux.c index fad12ff65c..59c7cdc285 100644 --- a/src/core/lib/iomgr/ev_epollsig_linux.c +++ b/src/core/lib/iomgr/ev_epollsig_linux.c @@ -39,6 +39,7 @@ #include <grpc/support/tls.h> #include <grpc/support/useful.h> +#include "src/core/lib/debug/stats.h" #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/lockfree_event.h" @@ -1236,6 +1237,7 @@ static void pollset_work_and_unlock(grpc_exec_ctx *exec_ctx, g_current_thread_polling_island = pi; GRPC_SCHEDULING_START_BLOCKING_REGION; + GRPC_STATS_INC_SYSCALL_POLL(exec_ctx); ep_rv = epoll_pwait(epoll_fd, ep_ev, GRPC_EPOLL_MAX_EVENTS, timeout_ms, sig_mask); GRPC_SCHEDULING_END_BLOCKING_REGION; diff --git a/src/core/lib/iomgr/ev_poll_posix.c b/src/core/lib/iomgr/ev_poll_posix.c index 9472a8e520..fbd265f3ce 100644 --- a/src/core/lib/iomgr/ev_poll_posix.c +++ b/src/core/lib/iomgr/ev_poll_posix.c @@ -36,6 +36,7 @@ #include <grpc/support/tls.h> #include <grpc/support/useful.h> +#include "src/core/lib/debug/stats.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/wakeup_fd_cv.h" @@ -983,6 +984,7 @@ static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, /* TODO(vpai): Consider first doing a 0 timeout poll here to avoid even going into the blocking annotation if possible */ GRPC_SCHEDULING_START_BLOCKING_REGION; + GRPC_STATS_INC_SYSCALL_POLL(exec_ctx); r = grpc_poll_function(pfds, pfd_count, timeout); GRPC_SCHEDULING_END_BLOCKING_REGION; diff --git a/src/core/lib/iomgr/exec_ctx.h b/src/core/lib/iomgr/exec_ctx.h index a0d2a965d5..c89792c8c4 100644 --- a/src/core/lib/iomgr/exec_ctx.h +++ b/src/core/lib/iomgr/exec_ctx.h @@ -19,6 +19,7 @@ #ifndef GRPC_CORE_LIB_IOMGR_EXEC_CTX_H #define GRPC_CORE_LIB_IOMGR_EXEC_CTX_H +#include <grpc/support/cpu.h> #include "src/core/lib/iomgr/closure.h" /* #define GRPC_EXECUTION_CONTEXT_SANITIZER 1 */ @@ -62,6 +63,7 @@ struct grpc_exec_ctx { /** last active combiner in the active combiner list */ grpc_combiner *last_combiner; uintptr_t flags; + unsigned starting_cpu; void *check_ready_to_finish_arg; bool (*check_ready_to_finish)(grpc_exec_ctx *exec_ctx, void *arg); }; @@ -69,7 +71,10 @@ struct grpc_exec_ctx { /* initializer for grpc_exec_ctx: prefer to use GRPC_EXEC_CTX_INIT whenever possible */ #define GRPC_EXEC_CTX_INITIALIZER(flags, finish_check, finish_check_arg) \ - { GRPC_CLOSURE_LIST_INIT, NULL, NULL, flags, finish_check_arg, finish_check } + { \ + GRPC_CLOSURE_LIST_INIT, NULL, NULL, flags, gpr_cpu_current_cpu(), \ + finish_check_arg, finish_check \ + } /* initialize an execution context at the top level of an API call into grpc (this is safe to use elsewhere, though possibly not as efficient) */ diff --git a/src/core/lib/iomgr/iocp_windows.c b/src/core/lib/iomgr/iocp_windows.c index e343f8a794..c082179c0b 100644 --- a/src/core/lib/iomgr/iocp_windows.c +++ b/src/core/lib/iomgr/iocp_windows.c @@ -27,6 +27,7 @@ #include <grpc/support/log_windows.h> #include <grpc/support/thd.h> +#include "src/core/lib/debug/stats.h" #include "src/core/lib/iomgr/iocp_windows.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/socket_windows.h" @@ -65,6 +66,7 @@ grpc_iocp_work_status grpc_iocp_work(grpc_exec_ctx *exec_ctx, LPOVERLAPPED overlapped; grpc_winsocket *socket; grpc_winsocket_callback_info *info; + GRPC_STATS_INC_SYSCALL_POLL(exec_ctx); success = GetQueuedCompletionStatus( g_iocp, &bytes, &completion_key, &overlapped, deadline_to_millis_timeout(deadline, gpr_now(deadline.clock_type))); diff --git a/src/core/lib/iomgr/tcp_posix.c b/src/core/lib/iomgr/tcp_posix.c index 2f543fd8a9..7e789cc5b5 100644 --- a/src/core/lib/iomgr/tcp_posix.c +++ b/src/core/lib/iomgr/tcp_posix.c @@ -40,6 +40,7 @@ #include <grpc/support/useful.h> #include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/debug/stats.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/profiling/timers.h" @@ -258,6 +259,7 @@ static void tcp_do_read(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) { GPR_TIMER_BEGIN("recvmsg", 0); do { + GRPC_STATS_INC_SYSCALL_READ(exec_ctx); read_bytes = recvmsg(tcp->fd, &msg, 0); } while (read_bytes < 0 && errno == EINTR); GPR_TIMER_END("recvmsg", read_bytes >= 0); @@ -361,7 +363,8 @@ static void tcp_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, /* returns true if done, false if pending; if returning true, *error is set */ #define MAX_WRITE_IOVEC 1000 -static bool tcp_flush(grpc_tcp *tcp, grpc_error **error) { +static bool tcp_flush(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp, + grpc_error **error) { struct msghdr msg; struct iovec iov[MAX_WRITE_IOVEC]; msg_iovlen_type iov_size; @@ -403,6 +406,7 @@ static bool tcp_flush(grpc_tcp *tcp, grpc_error **error) { GPR_TIMER_BEGIN("sendmsg", 1); do { /* TODO(klempner): Cork if this is a partial write */ + GRPC_STATS_INC_SYSCALL_WRITE(exec_ctx); sent_length = sendmsg(tcp->fd, &msg, SENDMSG_FLAGS); } while (sent_length < 0 && errno == EINTR); GPR_TIMER_END("sendmsg", 0); @@ -459,7 +463,7 @@ static void tcp_handle_write(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */, return; } - if (!tcp_flush(tcp, &error)) { + if (!tcp_flush(exec_ctx, tcp, &error)) { if (GRPC_TRACER_ON(grpc_tcp_trace)) { gpr_log(GPR_DEBUG, "write: delayed"); } @@ -510,7 +514,7 @@ static void tcp_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, tcp->outgoing_slice_idx = 0; tcp->outgoing_byte_idx = 0; - if (!tcp_flush(tcp, &error)) { + if (!tcp_flush(exec_ctx, tcp, &error)) { TCP_REF(tcp, "write"); tcp->write_cb = cb; if (GRPC_TRACER_ON(grpc_tcp_trace)) { diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index 62d542d2c5..e68c201134 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -32,6 +32,7 @@ #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/compression/algorithm_metadata.h" +#include "src/core/lib/debug/stats.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" @@ -334,6 +335,11 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx, /* Always support no compression */ GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_COMPRESS_NONE); call->is_client = args->server_transport_data == NULL; + if (call->is_client) { + GRPC_STATS_INC_CLIENT_CALLS_CREATED(exec_ctx); + } else { + GRPC_STATS_INC_SERVER_CALLS_CREATED(exec_ctx); + } call->stream_op_payload.context = call->context; grpc_slice path = grpc_empty_slice(); if (call->is_client) { diff --git a/src/core/lib/surface/init.c b/src/core/lib/surface/init.c index d199ac060e..898476daee 100644 --- a/src/core/lib/surface/init.c +++ b/src/core/lib/surface/init.c @@ -28,6 +28,7 @@ #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/connected_channel.h" #include "src/core/lib/channel/handshaker_registry.h" +#include "src/core/lib/debug/stats.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/iomgr/combiner.h" @@ -118,6 +119,7 @@ void grpc_init(void) { gpr_mu_lock(&g_init_mu); if (++g_initializations == 1) { gpr_time_init(); + grpc_stats_init(); grpc_slice_intern_init(); grpc_mdctx_global_init(); grpc_channel_init_init(); @@ -186,6 +188,7 @@ void grpc_shutdown(void) { grpc_mdctx_global_shutdown(&exec_ctx); grpc_handshaker_factory_registry_shutdown(&exec_ctx); grpc_slice_intern_shutdown(); + grpc_stats_shutdown(); } gpr_mu_unlock(&g_init_mu); grpc_exec_ctx_finish(&exec_ctx); |