Classify the tracer object

reviewable/pr13883/r1
ncteisen 7 years ago
parent b04efac6a5
commit 6572ce2c4a
  1. 2
      src/core/ext/filters/client_channel/subchannel.cc
  2. 370
      src/core/lib/channel/channel_tracer.cc
  3. 84
      src/core/lib/channel/channel_tracer.h
  4. 2
      src/core/lib/support/object_registry.cc
  5. 17
      src/core/lib/surface/channel.cc
  6. 214
      test/core/channel/channel_tracer_test.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 {

@ -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<grpc_channel_tracer*>(
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<grpc_trace_node*>(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<grpc_channel_tracer*>(object), recursive);
return static_cast<ChannelTracer*>(object)->RenderTrace(recursive);
}
} // namespace grpc_core

@ -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 */

@ -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) {

@ -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<grpc_core::ChannelTracer>(
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; }

@ -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) {

Loading…
Cancel
Save