aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/lib/channel
diff options
context:
space:
mode:
authorGravatar ncteisen <ncteisen@gmail.com>2018-03-02 15:16:50 -0800
committerGravatar ncteisen <ncteisen@gmail.com>2018-03-02 15:16:50 -0800
commitcd6755b13c7227dbfea2f8f8385b41eca15da8ca (patch)
treee56815eeba0dcc4e96beacbad169d723edafa1e1 /src/core/lib/channel
parent77917688b92974a716b608325b757a907b367047 (diff)
Re write rendered
Diffstat (limited to 'src/core/lib/channel')
-rw-r--r--src/core/lib/channel/channel_tracer.cc191
-rw-r--r--src/core/lib/channel/channel_tracer.h39
2 files changed, 72 insertions, 158 deletions
diff --git a/src/core/lib/channel/channel_tracer.cc b/src/core/lib/channel/channel_tracer.cc
index 092a22fcf0..86b7a6cce9 100644
--- a/src/core/lib/channel/channel_tracer.cc
+++ b/src/core/lib/channel/channel_tracer.cc
@@ -123,156 +123,59 @@ char* fmt_time(gpr_timespec tm) {
} // anonymous namespace
-class ChannelTraceRenderer {
- public:
- // If recursive==true, then the entire tree of trace will be rendered.
- // If not, then only the top level data will be.
- ChannelTraceRenderer(ChannelTrace* tracer, bool recursive)
- : current_tracer_(tracer),
- recursive_(recursive),
- seen_tracers_(nullptr),
- size_(0),
- cap_(0) {}
-
- // Renders the trace and returns an allocated char* with the formatted JSON
- 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, 0);
- grpc_json_destroy(json);
- return json_str;
- }
-
- private:
- // tracks that a tracer has already been rendered to avoid infinite
- // recursion.
- void AddSeenTracer(ChannelTrace* newly_seen) {
- if (size_ >= cap_) {
- cap_ = GPR_MAX(5 * sizeof(newly_seen), 3 * cap_ / 2);
- seen_tracers_ = (ChannelTrace**)gpr_realloc(seen_tracers_, cap_);
- }
- seen_tracers_[size_++] = newly_seen;
+void ChannelTrace::TraceEvent::RenderTraceEvent(grpc_json* json) {
+ grpc_json* json_iterator = nullptr;
+ json_iterator = grpc_json_create_child(json_iterator, json, "description",
+ grpc_slice_to_c_string(data_),
+ GRPC_JSON_STRING, true);
+ // TODO(ncteisen): Either format this as google.rpc.Status here, or ensure
+ // it is done in the layers above core.
+ if (error_ != GRPC_ERROR_NONE) {
+ json_iterator = grpc_json_create_child(
+ json_iterator, json, "status", gpr_strdup(grpc_error_string(error_)),
+ GRPC_JSON_STRING, true);
}
-
- // Checks if a tracer has already been seen.
- bool TracerAlreadySeen(ChannelTrace* tracer) {
- for (size_t i = 0; i < size_; ++i) {
- if (seen_tracers_[i] == tracer) return true;
- }
- return false;
- }
-
- // Recursively fills up json by walking over all of the trace of
- // current_tracer_. Starts at the top level, by creating the fields
- // channelData, and childData.
- 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, "childData",
- nullptr, GRPC_JSON_ARRAY, false);
- }
- PopulateChannelData(channel_data, children);
- }
-
- // Fills up the channelData object. If children is not null, it will
- // recursively populate each referenced child as it passes that event.
- void PopulateChannelData(grpc_json* channel_data, grpc_json* children) {
- grpc_json* child = nullptr;
+ json_iterator =
+ grpc_json_create_child(json_iterator, json, "timestamp",
+ fmt_time(time_created_), GRPC_JSON_STRING, true);
+ json_iterator =
+ grpc_json_create_child(json_iterator, json, "state",
+ grpc_connectivity_state_name(connectivity_state_),
+ GRPC_JSON_STRING, false);
+ if (referenced_tracer_ != nullptr) {
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_events_logged_str;
- gpr_asprintf(&num_events_logged_str, "%" PRId64,
- current_tracer_->num_events_logged_);
- child =
- grpc_json_create_child(child, channel_data, "numNodesLogged",
- num_events_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);
+ gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_tracer_->channel_uuid_);
+ json_iterator = grpc_json_create_child(json_iterator, json, "child_ref",
+ uuid_str, GRPC_JSON_NUMBER, true);
}
+}
- // Iterated over the list of TraceEvents and populates their data.
- void PopulateNodeList(grpc_json* nodes, grpc_json* children) {
- grpc_json* child = nullptr;
- ChannelTrace::TraceEvent* 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_;
- }
- }
-
- // Fills in all the data for a single TraceEvent. If children is not null
- // and the TraceEvent refers to a child Tracer object and recursive_ is true,
- // then that child object will be rendered into the trace.
- void PopulateNode(ChannelTrace::TraceEvent* 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 we are recursively populating everything, and this node
- // references a tracer we haven't seen yet, we render that tracer
- // in full, adding it to the parent JSON's "children" field.
- if (children && !TracerAlreadySeen(node->referenced_tracer_.get())) {
- grpc_json* referenced_tracer = grpc_json_create_child(
- nullptr, children, nullptr, nullptr, GRPC_JSON_OBJECT, false);
- AddSeenTracer(node->referenced_tracer_.get());
- ChannelTrace* saved = current_tracer_;
- current_tracer_ = node->referenced_tracer_.get();
- RecursivelyPopulateJson(referenced_tracer);
- current_tracer_ = saved;
- }
- }
- }
-
- // Tracks the current tracer we are rendering as we walk the tree of tracers.
- ChannelTrace* current_tracer_;
-
- // If true, we will render the data of all of this tracer's children.
- bool recursive_;
-
- // These members are used to track tracers we have already rendered. This is
- // a dynamically growing array that is deallocated when the rendering is done.
- ChannelTrace** seen_tracers_;
- size_t size_;
- size_t cap_;
-};
-
-char* ChannelTrace::RenderTrace(bool recursive) {
+char* ChannelTrace::RenderTrace() {
if (!max_list_size_)
return nullptr; // tracing is disabled if max_events == 0
- ChannelTraceRenderer renderer(this, recursive);
- return renderer.Run();
+ grpc_json* json = grpc_json_create(GRPC_JSON_OBJECT);
+ char* num_events_logged_str;
+ gpr_asprintf(&num_events_logged_str, "%" PRId64, num_events_logged_);
+ grpc_json* json_iterator = nullptr;
+ json_iterator =
+ grpc_json_create_child(json_iterator, json, "num_events_logged",
+ num_events_logged_str, GRPC_JSON_NUMBER, true);
+ json_iterator =
+ grpc_json_create_child(json_iterator, json, "creation_time",
+ fmt_time(time_created_), GRPC_JSON_STRING, true);
+ grpc_json* events = grpc_json_create_child(json_iterator, json, "events",
+ nullptr, GRPC_JSON_ARRAY, false);
+ json_iterator = nullptr;
+ TraceEvent* it = head_trace_;
+ while (it != nullptr) {
+ json_iterator = grpc_json_create_child(json_iterator, events, nullptr,
+ nullptr, GRPC_JSON_OBJECT, false);
+ it->RenderTraceEvent(json_iterator);
+ it = it->next();
+ }
+ char* json_str = grpc_json_dump_to_string(json, 0);
+ grpc_json_destroy(json);
+ return json_str;
}
} // namespace grpc_core
diff --git a/src/core/lib/channel/channel_tracer.h b/src/core/lib/channel/channel_tracer.h
index 4547a0fb0b..976e66c49e 100644
--- a/src/core/lib/channel/channel_tracer.h
+++ b/src/core/lib/channel/channel_tracer.h
@@ -29,38 +29,44 @@
namespace grpc_core {
+// Object used to hold live data for a channel. This data is exposed via the
+// channelz service:
+// https://github.com/grpc/proposal/blob/master/A14-channelz.md
class ChannelTrace : public RefCounted<ChannelTrace> {
public:
ChannelTrace(size_t max_events);
~ChannelTrace();
- /* returns the tracer's uuid */
+ // returns the tracer's uuid
intptr_t GetUuid();
- /* Adds a new trace event to the tracing object */
+ // Adds a new trace event to the tracing object
void AddTraceEvent(grpc_slice data, grpc_error* error,
grpc_connectivity_state connectivity_state);
- /* Adds a new trace event to the tracing object. This trace event refers to a
- an event on a child of the channel. For example this could log when a
- particular subchannel becomes connected.
- TODO(ncteisen): Once channelz is implemented, the events should reference
- the channelz object, not the channel trace. */
+ // Adds a new trace event to the tracing object. This trace event refers to a
+ // an event on a child of the channel. For example, if this channel has
+ // created a new subchannel, then it would record that with a TraceEvent
+ // referencing the new subchannel.
+
+ // TODO(ncteisen): Once channelz is implemented, the events should reference
+ // the overall channelz object, not just the ChannelTrace object.
void AddTraceEvent(grpc_slice data, grpc_error* error,
grpc_connectivity_state connectivity_state,
RefCountedPtr<ChannelTrace> referenced_tracer);
- /* 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);
+ // Returns the tracing data rendered as a grpc json string.
+ // The string is owned by the caller and must be freed.
+ char* RenderTrace();
private:
// Private class to encapsulate all the data and bookkeeping needed for a
// a trace event.
class TraceEvent {
public:
+ // Constructor for a TraceEvent that references a different channel.
+ // TODO(ncteisen): once channelz is implemented, this should reference the
+ // overall channelz object, not just the ChannelTrace object
TraceEvent(grpc_slice data, grpc_error* error,
grpc_connectivity_state connectivity_state,
RefCountedPtr<ChannelTrace> referenced_tracer)
@@ -72,6 +78,8 @@ class ChannelTrace : public RefCounted<ChannelTrace> {
time_created_ = gpr_now(GPR_CLOCK_REALTIME);
}
+ // Constructor for a TraceEvent that does not reverence a different
+ // channel.
TraceEvent(grpc_slice data, grpc_error* error,
grpc_connectivity_state connectivity_state)
: data_(data),
@@ -84,11 +92,15 @@ class ChannelTrace : public RefCounted<ChannelTrace> {
~TraceEvent();
+ // Renders the data inside of this TraceEvent into a json object. This is
+ // used by the ChannelTrace, when it is rendering itself.
+ void RenderTraceEvent(grpc_json* json);
+
+ // set and get for the next_ pointer.
TraceEvent* next() { return next_; }
void set_next(TraceEvent* next) { next_ = next; }
private:
- friend class ChannelTraceRenderer;
grpc_slice data_;
grpc_error* error_;
gpr_timespec time_created_;
@@ -101,7 +113,6 @@ class ChannelTrace : public RefCounted<ChannelTrace> {
// Internal helper to add and link in a trace event
void AddTraceEventHelper(TraceEvent* new_trace_event);
- friend class ChannelTraceRenderer;
gpr_mu tracer_mu_;
intptr_t channel_uuid_;
uint64_t num_events_logged_;