diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index f4b6c2a161d..0310f152cce 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -137,7 +137,7 @@ struct grpc_subchannel { /** our alarm */ grpc_timer alarm; - grpc_channel_tracer* tracer; + grpc_core::ChannelTracer* tracer; }; struct grpc_subchannel_call { diff --git a/src/core/lib/channel/channel_tracer.cc b/src/core/lib/channel/channel_tracer.cc index e2d3b7ae088..e93fbc29d85 100644 --- a/src/core/lib/channel/channel_tracer.cc +++ b/src/core/lib/channel/channel_tracer.cc @@ -32,6 +32,8 @@ #include "src/core/lib/surface/channel.h" #include "src/core/lib/transport/connectivity_state.h" +namespace grpc_core { + grpc_core::DebugOnlyTraceFlag grpc_trace_channel_tracer_refcount( false, "channel_tracer_refcount"); @@ -44,116 +46,55 @@ typedef struct grpc_trace_node { struct grpc_trace_node* next; // the tracer object for the (sub)channel that this trace node refers to. - grpc_channel_tracer* referenced_tracer; + ChannelTracer* 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; -}; - -#ifndef NDEBUG -grpc_channel_tracer* grpc_channel_tracer_create(size_t max_nodes, - const char* file, int line, - const char* func) { -#else -grpc_channel_tracer* grpc_channel_tracer_create(size_t max_nodes) { -#endif - grpc_channel_tracer* tracer = static_cast( - gpr_zalloc(sizeof(grpc_channel_tracer))); - gpr_mu_init(&tracer->tracer_mu); - gpr_ref_init(&tracer->refs, 1); -#ifndef NDEBUG - if (grpc_trace_channel_tracer_refcount.enabled()) { - gpr_log(GPR_DEBUG, "%p create [%s:%d %s]", tracer, file, line, func); - } -#endif - tracer->channel_uuid = grpc_object_registry_register_object( - tracer, GRPC_OBJECT_REGISTRY_CHANNEL_TRACER); - tracer->max_list_size = max_nodes; - tracer->time_created = gpr_now(GPR_CLOCK_REALTIME); - return tracer; +ChannelTracer::ChannelTracer(size_t max_nodes) + : num_nodes_logged(0), + list_size(0), + max_list_size(max_nodes), + head_trace(0), + tail_trace(0) { + gpr_mu_init(&tracer_mu); + gpr_ref_init(&refs, 1); + channel_uuid = grpc_object_registry_register_object( + this, GRPC_OBJECT_REGISTRY_CHANNEL_TRACER); + max_list_size = max_nodes; + time_created = gpr_now(GPR_CLOCK_REALTIME); } -#ifndef NDEBUG -grpc_channel_tracer* grpc_channel_tracer_ref(grpc_channel_tracer* tracer, - const char* file, int line, - const char* func) { - if (!tracer) return tracer; - if (grpc_trace_channel_tracer_refcount.enabled()) { - 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; +ChannelTracer* ChannelTracer::Ref() { + gpr_ref(&refs); + return this; } -#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); + if (node->referenced_tracer) { + node->referenced_tracer->Unref(); + } 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 != nullptr) { - grpc_trace_node* to_free = it; - it = it->next; - free_node(to_free); - } - gpr_mu_destroy(&tracer->tracer_mu); - gpr_free(tracer); -} - -#ifndef NDEBUG -void grpc_channel_tracer_unref(grpc_channel_tracer* tracer, const char* file, - int line, const char* func) { - if (!tracer) return; - if (grpc_trace_channel_tracer_refcount.enabled()) { - 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); +void ChannelTracer::Unref() { + if (gpr_unref(&refs)) { + grpc_trace_node* it = head_trace; + while (it != nullptr) { + grpc_trace_node* to_free = it; + it = it->next; + free_node(to_free); + } + gpr_mu_destroy(&tracer_mu); } } -#endif -intptr_t grpc_channel_tracer_get_uuid(grpc_channel_tracer* tracer) { - return tracer->channel_uuid; -} +intptr_t ChannelTracer::GetUuid() { return channel_uuid; } -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; +void ChannelTracer::AddTrace(grpc_slice data, grpc_error* error, + grpc_connectivity_state connectivity_state, + ChannelTracer* referenced_tracer) { + ++num_nodes_logged; // create and fill up the new node grpc_trace_node* new_trace_node = static_cast(gpr_malloc(sizeof(grpc_trace_node))); @@ -163,23 +104,23 @@ void grpc_channel_tracer_add_trace(grpc_channel_tracer* tracer, grpc_slice data, new_trace_node->connectivity_state = connectivity_state; new_trace_node->next = nullptr; new_trace_node->referenced_tracer = - GRPC_CHANNEL_TRACER_REF(referenced_tracer); + (referenced_tracer) ? referenced_tracer->Ref() : nullptr; // first node case - if (tracer->head_trace == nullptr) { - tracer->head_trace = tracer->tail_trace = new_trace_node; + if (head_trace == nullptr) { + head_trace = tail_trace = new_trace_node; } // regular node add case else { - tracer->tail_trace->next = new_trace_node; - tracer->tail_trace = tracer->tail_trace->next; + tail_trace->next = new_trace_node; + tail_trace = tail_trace->next; } - ++tracer->list_size; + ++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; + if (list_size > max_list_size) { + grpc_trace_node* to_free = head_trace; + head_trace = head_trace->next; free_node(to_free); - --tracer->list_size; + --list_size; } } @@ -193,135 +134,138 @@ static char* fmt_time(gpr_timespec tm) { return full_time_str; } -typedef struct seen_tracers { - grpc_channel_tracer** tracers; - size_t size; - size_t cap; -} seen_tracers; +class ChannelTracerRenderer { + public: + ChannelTracerRenderer(ChannelTracer* tracer, bool recursive) + : current_tracer_(tracer), + recursive_(recursive), + seen_tracers_(nullptr), + size_(0), + cap_(0) {} -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); + char* Run() { + grpc_json* json = grpc_json_create(GRPC_JSON_OBJECT); + AddSeenTracer(current_tracer_); + RecursivelyPopulateJson(json); + gpr_free(seen_tracers_); + char* json_str = grpc_json_dump_to_string(json, 1); + grpc_json_destroy(json); + return json_str; } - 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; + private: + void AddSeenTracer(ChannelTracer* newly_seen) { + if (size_ >= cap_) { + cap_ = GPR_MAX(5 * sizeof(newly_seen), 3 * cap_ / 2); + seen_tracers_ = (ChannelTracer**)gpr_realloc(seen_tracers_, cap_); + } + seen_tracers_[size_++] = newly_seen; } - 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 = nullptr; - 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 != nullptr) { - char* uuid_str; - gpr_asprintf(&uuid_str, "%" PRIdPTR, 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( - nullptr, children, nullptr, nullptr, GRPC_JSON_OBJECT, false); - recursively_populate_json(node->referenced_tracer, tracker, - referenced_tracer, true); + bool TracerAlreadySeen(ChannelTracer* tracer) { + for (size_t i = 0; i < size_; ++i) { + if (seen_tracers_[i] == tracer) return true; } + return false; } -} -static void populate_node_list_data(grpc_channel_tracer* tracer, - seen_tracers* tracker, grpc_json* nodes, - grpc_json* children) { - grpc_json* child = nullptr; - grpc_trace_node* it = tracer->head_trace; - while (it != nullptr) { - child = grpc_json_create_child(child, nodes, nullptr, nullptr, - GRPC_JSON_OBJECT, false); - populate_node_data(it, tracker, child, children); - it = it->next; + void RecursivelyPopulateJson(grpc_json* json) { + grpc_json* channel_data = grpc_json_create_child( + nullptr, json, "channelData", nullptr, GRPC_JSON_OBJECT, false); + grpc_json* children = nullptr; + if (recursive_) { + children = grpc_json_create_child(channel_data, json, "children", nullptr, + GRPC_JSON_ARRAY, false); + } + PopulateTracer(channel_data, children); } -} -static void populate_tracer_data(grpc_channel_tracer* tracer, - seen_tracers* tracker, grpc_json* channel_data, - grpc_json* children) { - grpc_json* child = nullptr; + void PopulateTracer(grpc_json* channel_data, grpc_json* children) { + grpc_json* child = nullptr; - char* uuid_str; - gpr_asprintf(&uuid_str, "%" PRIdPTR, 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", nullptr, - 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( - nullptr, json, "channelData", nullptr, GRPC_JSON_OBJECT, false); - grpc_json* children = nullptr; - if (recursive) { - children = grpc_json_create_child(channel_data, json, "children", nullptr, - GRPC_JSON_ARRAY, false); + char* uuid_str; + gpr_asprintf(&uuid_str, "%" PRIdPTR, current_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, + current_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(current_tracer_->time_created), + GRPC_JSON_STRING, true); + child = grpc_json_create_child(child, channel_data, "nodes", nullptr, + GRPC_JSON_ARRAY, false); + PopulateNodeList(child, children); } - 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)); + void PopulateNodeList(grpc_json* nodes, grpc_json* children) { + grpc_json* child = nullptr; + grpc_trace_node* it = current_tracer_->head_trace; + while (it != nullptr) { + child = grpc_json_create_child(child, nodes, nullptr, nullptr, + GRPC_JSON_OBJECT, false); + PopulateNode(it, child, children); + it = it->next; + } + } - recursively_populate_json(tracer, &tracker, json, recursive); + void PopulateNode(grpc_trace_node* node, grpc_json* json, + grpc_json* children) { + grpc_json* child = nullptr; + 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 != nullptr) { + char* uuid_str; + gpr_asprintf(&uuid_str, "%" PRIdPTR, + node->referenced_tracer->channel_uuid); + child = grpc_json_create_child(child, json, "uuid", uuid_str, + GRPC_JSON_NUMBER, true); + if (children && !TracerAlreadySeen(node->referenced_tracer)) { + grpc_json* referenced_tracer = grpc_json_create_child( + nullptr, children, nullptr, nullptr, GRPC_JSON_OBJECT, false); + AddSeenTracer(node->referenced_tracer); + ChannelTracer* saved = current_tracer_; + current_tracer_ = node->referenced_tracer; + RecursivelyPopulateJson(referenced_tracer); + current_tracer_ = saved; + } + } + } - gpr_free(tracker.tracers); + ChannelTracer* current_tracer_; + bool recursive_; + ChannelTracer** seen_tracers_; + size_t size_; + size_t cap_; +}; - char* json_str = grpc_json_dump_to_string(json, 1); - grpc_json_destroy(json); - return json_str; +char* ChannelTracer::RenderTrace(bool recursive) { + ChannelTracerRenderer renderer(this, recursive); + return renderer.Run(); } -char* grpc_channel_tracer_get_trace(intptr_t uuid, bool recursive) { +char* ChannelTracer::GetChannelTraceFromUuid(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_TRACER); - return grpc_channel_tracer_render_trace( - static_cast(object), recursive); + return static_cast(object)->RenderTrace(recursive); } + +} // namespace grpc_core diff --git a/src/core/lib/channel/channel_tracer.h b/src/core/lib/channel/channel_tracer.h index 5c34f1bc441..6b7d719028c 100644 --- a/src/core/lib/channel/channel_tracer.h +++ b/src/core/lib/channel/channel_tracer.h @@ -23,58 +23,52 @@ #include "src/core/lib/iomgr/error.h" #include "src/core/lib/json/json.h" -/* Forward declaration */ -typedef struct grpc_channel_tracer grpc_channel_tracer; +namespace grpc_core { extern grpc_core::DebugOnlyTraceFlag grpc_trace_channel_tracer_refcount; -/* Creates a new tracer. The caller owns a reference to the returned tracer. */ -#ifndef NDEBUG -grpc_channel_tracer* grpc_channel_tracer_create(size_t max_nodes, - const char* file, int line, - const char* func); -#define GRPC_CHANNEL_TRACER_CREATE(max_nodes) \ - grpc_channel_tracer_create(max_nodes, __FILE__, __LINE__, __func__) -#else -grpc_channel_tracer* grpc_channel_tracer_create(size_t max_nodes); -#define GRPC_CHANNEL_TRACER_CREATE(max_nodes) \ - grpc_channel_tracer_create(max_nodes) -#endif +typedef struct grpc_trace_node grpc_trace_node; -#ifndef NDEBUG -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 +class ChannelTracer { + public: + ChannelTracer(size_t max_nodes); + ~ChannelTracer() {} -/* returns the tracers uuid */ -intptr_t grpc_channel_tracer_get_uuid(grpc_channel_tracer* tracer); + // TODO(ncteisen): incorporate RefCounted class + ChannelTracer* Ref(); + void Unref(); -/* 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 tracers uuid */ + intptr_t GetUuid(); -/* 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 + /* Adds a new trace node to the tracing object */ + void AddTrace(grpc_slice data, grpc_error* error, + grpc_connectivity_state connectivity_state, + ChannelTracer* 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* RenderTrace(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); + static char* GetChannelTraceFromUuid(intptr_t uuid, bool recursive); + + private: + friend class ChannelTracerRenderer; + 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; +}; + +} // namespace grpc_core #endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_TRACER_H */ diff --git a/src/core/lib/support/object_registry.cc b/src/core/lib/support/object_registry.cc index bd19bb13a6e..72403a4f767 100644 --- a/src/core/lib/support/object_registry.cc +++ b/src/core/lib/support/object_registry.cc @@ -37,7 +37,7 @@ typedef struct { 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; + return (intptr_t)key1 - (intptr_t)key2; } static void destroy_tracker(void* tracker, void* user_data) { diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc index 35e94f5dc1d..e80c36465e4 100644 --- a/src/core/lib/surface/channel.cc +++ b/src/core/lib/surface/channel.cc @@ -32,6 +32,7 @@ #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/memory.h" #include "src/core/lib/support/object_registry.h" #include "src/core/lib/support/string.h" #include "src/core/lib/surface/api_trace.h" @@ -63,7 +64,7 @@ struct grpc_channel { gpr_mu registered_call_mu; registered_call* registered_calls; - grpc_channel_tracer* tracer; + grpc_core::ChannelTracer* tracer; char* target; }; @@ -202,23 +203,21 @@ grpc_channel* grpc_channel_create_with_builder( 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 = grpc_channel_tracer_get_uuid(channel->tracer); + channel->tracer = grpc_core::New( + max_nodes); // TODO(ncteisen): leaky yo + channel->uuid = channel->tracer->GetUuid(); } } } 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, nullptr); + channel->tracer->AddTrace(grpc_slice_from_static_string("Channel created"), + GRPC_ERROR_NONE, GRPC_CHANNEL_IDLE, nullptr); return channel; } char* grpc_channel_get_trace(grpc_channel* channel, bool recursive) { - return channel->tracer - ? grpc_channel_tracer_render_trace(channel->tracer, recursive) - : nullptr; + return channel->tracer ? channel->tracer->RenderTrace(recursive) : nullptr; } intptr_t grpc_channel_get_uuid(grpc_channel* channel) { return channel->uuid; } diff --git a/test/core/channel/channel_tracer_test.cc b/test/core/channel/channel_tracer_test.cc index 4f1ce160a1a..131ea567fc9 100644 --- a/test/core/channel/channel_tracer_test.cc +++ b/test/core/channel/channel_tracer_test.cc @@ -29,18 +29,19 @@ #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, nullptr); +using grpc_core::ChannelTracer; + +static void add_simple_trace(ChannelTracer* tracer) { + tracer->AddTrace(grpc_slice_from_static_string("simple trace"), + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), + GRPC_CHANNEL_READY, nullptr); } // checks for the existence of all the required members of the tracer. -static void validate_tracer(grpc_channel_tracer* tracer, +static void validate_tracer(ChannelTracer* tracer, size_t expected_num_nodes_logged, size_t max_nodes) { - char* json_str = grpc_channel_tracer_render_trace(tracer, true); + char* json_str = tracer->RenderTrace(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)); @@ -48,10 +49,20 @@ static void validate_tracer(grpc_channel_tracer* tracer, gpr_free(json_str); } +static void validate_tracer_data_matches_uuid_lookup(ChannelTracer* tracer) { + intptr_t uuid = tracer->GetUuid(); + char* tracer_json_str = tracer->RenderTrace(true); + char* uuid_lookup_json_str = + ChannelTracer::GetChannelTraceFromUuid(uuid, true); + strcmp(tracer_json_str, uuid_lookup_json_str); + gpr_free(tracer_json_str); + gpr_free(uuid_lookup_json_str); +} + // ensures the tracer has the correct number of children tracers. -static void validate_children(grpc_channel_tracer* tracer, +static void validate_children(ChannelTracer* tracer, size_t expected_num_children) { - char* json_str = grpc_channel_tracer_render_trace(tracer, true); + char* json_str = tracer->RenderTrace(true); grpc_json* json = grpc_json_parse_string(json_str); validate_json_array_size(json, "children", expected_num_children); grpc_json_destroy(json); @@ -59,28 +70,29 @@ static void validate_children(grpc_channel_tracer* tracer, } static void test_basic_channel_tracing(size_t max_nodes) { - grpc_channel_tracer* tracer = GRPC_CHANNEL_TRACER_CREATE(max_nodes); 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"), + ChannelTracer tracer(max_nodes); + add_simple_trace(&tracer); + add_simple_trace(&tracer); + validate_tracer_data_matches_uuid_lookup(&tracer); + tracer.AddTrace( + 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, nullptr); - grpc_channel_tracer_add_trace( - tracer, grpc_slice_from_static_string("trace four"), GRPC_ERROR_NONE, - GRPC_CHANNEL_SHUTDOWN, nullptr); - 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); + tracer.AddTrace(grpc_slice_from_static_string("trace four"), GRPC_ERROR_NONE, + GRPC_CHANNEL_SHUTDOWN, nullptr); + 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); + validate_tracer_data_matches_uuid_lookup(&tracer); + tracer.Unref(); } static void test_basic_channel_sizing() { @@ -93,43 +105,42 @@ static void test_basic_channel_sizing() { } static void test_complex_channel_tracing(size_t max_nodes) { - grpc_channel_tracer* tracer = GRPC_CHANNEL_TRACER_CREATE(max_nodes); grpc_core::ExecCtx exec_ctx; - add_simple_trace(tracer); - add_simple_trace(tracer); - grpc_channel_tracer* sc1 = GRPC_CHANNEL_TRACER_CREATE(max_nodes); - 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); - 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); + ChannelTracer tracer(max_nodes); + add_simple_trace(&tracer); + add_simple_trace(&tracer); + ChannelTracer sc1(max_nodes); + tracer.AddTrace(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); + validate_tracer_data_matches_uuid_lookup(&tracer); + ChannelTracer sc2(max_nodes); + tracer.AddTrace(grpc_slice_from_static_string("subchannel two created"), + GRPC_ERROR_NONE, GRPC_CHANNEL_IDLE, &sc2); + tracer.AddTrace(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); + // validate_tracer_data_matches_uuid_lookup(&tracer); + sc1.Unref(); + sc2.Unref(); + tracer.Unref(); } static void test_complex_channel_sizing() { @@ -142,57 +153,52 @@ static void test_complex_channel_sizing() { } static void test_delete_parent_first() { - grpc_channel_tracer* tracer = GRPC_CHANNEL_TRACER_CREATE(3); grpc_core::ExecCtx exec_ctx; - add_simple_trace(tracer); - add_simple_trace(tracer); - grpc_channel_tracer* sc1 = GRPC_CHANNEL_TRACER_CREATE(3); - grpc_channel_tracer_add_trace( - tracer, grpc_slice_from_static_string("subchannel one created"), - GRPC_ERROR_NONE, GRPC_CHANNEL_IDLE, sc1); + ChannelTracer tracer(3); + add_simple_trace(&tracer); + add_simple_trace(&tracer); + ChannelTracer sc1(3); + tracer.AddTrace(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); + tracer.Unref(); + sc1.Unref(); } static void test_nesting() { - grpc_channel_tracer* tracer = GRPC_CHANNEL_TRACER_CREATE(10); grpc_core::ExecCtx exec_ctx; - add_simple_trace(tracer); - add_simple_trace(tracer); - grpc_channel_tracer* sc1 = GRPC_CHANNEL_TRACER_CREATE(5); - grpc_channel_tracer_add_trace( - tracer, grpc_slice_from_static_string("subchannel one created"), - GRPC_ERROR_NONE, GRPC_CHANNEL_IDLE, sc1); + ChannelTracer tracer(10); + add_simple_trace(&tracer); + add_simple_trace(&tracer); + ChannelTracer sc1(5); + tracer.AddTrace(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); + validate_children(&tracer, 1); + add_simple_trace(&sc1); + ChannelTracer conn1(5); // 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); - 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); + sc1.AddTrace(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); + ChannelTracer sc2(5); + tracer.AddTrace(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); + tracer.AddTrace(grpc_slice_from_static_string("subchannel one inactive"), + GRPC_ERROR_NONE, GRPC_CHANNEL_IDLE, &sc1); + validate_children(&tracer, 2); + add_simple_trace(&tracer); + + conn1.Unref(); + sc1.Unref(); + sc2.Unref(); + tracer.Unref(); } int main(int argc, char** argv) {