|  | @@ -45,7 +45,7 @@ class TraceEvent {
 | 
	
		
			
				|  |  |          error_(error),
 | 
	
		
			
				|  |  |          connectivity_state_(connectivity_state),
 | 
	
		
			
				|  |  |          next_(nullptr),
 | 
	
		
			
				|  |  | -        referenced_tracer_(referenced_tracer) {
 | 
	
		
			
				|  |  | +        referenced_tracer_(std::move(referenced_tracer)) {
 | 
	
		
			
				|  |  |      time_created_ = gpr_now(GPR_CLOCK_REALTIME);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -59,6 +59,12 @@ class TraceEvent {
 | 
	
		
			
				|  |  |      time_created_ = gpr_now(GPR_CLOCK_REALTIME);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  ~TraceEvent() {
 | 
	
		
			
				|  |  | +    GRPC_ERROR_UNREF(error_);
 | 
	
		
			
				|  |  | +    referenced_tracer_.reset();
 | 
	
		
			
				|  |  | +    grpc_slice_unref_internal(data_);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |   private:
 | 
	
		
			
				|  |  |    friend class ChannelTracer;
 | 
	
		
			
				|  |  |    friend class ChannelTracerRenderer;
 | 
	
	
		
			
				|  | @@ -79,27 +85,20 @@ ChannelTracer::ChannelTracer(size_t max_nodes)
 | 
	
		
			
				|  |  |        max_list_size_(max_nodes),
 | 
	
		
			
				|  |  |        head_trace_(nullptr),
 | 
	
		
			
				|  |  |        tail_trace_(nullptr) {
 | 
	
		
			
				|  |  | -  if (!max_list_size_) return;  // tracing is disabled if max_nodes == 0
 | 
	
		
			
				|  |  | +  if (max_list_size_ == 0) return;  // tracing is disabled if max_nodes == 0
 | 
	
		
			
				|  |  |    gpr_mu_init(&tracer_mu_);
 | 
	
		
			
				|  |  |    channel_uuid_ = grpc_object_registry_register_object(
 | 
	
		
			
				|  |  |        this, GRPC_OBJECT_REGISTRY_CHANNEL_TRACER);
 | 
	
		
			
				|  |  |    time_created_ = gpr_now(GPR_CLOCK_REALTIME);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -void ChannelTracer::FreeNode(TraceEvent* node) {
 | 
	
		
			
				|  |  | -  GRPC_ERROR_UNREF(node->error_);
 | 
	
		
			
				|  |  | -  node->referenced_tracer_.reset(nullptr);
 | 
	
		
			
				|  |  | -  grpc_slice_unref_internal(node->data_);
 | 
	
		
			
				|  |  | -  gpr_free(node);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  ChannelTracer::~ChannelTracer() {
 | 
	
		
			
				|  |  | -  if (!max_list_size_) return;  // tracing is disabled if max_nodes == 0
 | 
	
		
			
				|  |  | +  if (max_list_size_ == 0) return;  // tracing is disabled if max_nodes == 0
 | 
	
		
			
				|  |  |    TraceEvent* it = head_trace_;
 | 
	
		
			
				|  |  |    while (it != nullptr) {
 | 
	
		
			
				|  |  |      TraceEvent* to_free = it;
 | 
	
		
			
				|  |  |      it = it->next_;
 | 
	
		
			
				|  |  | -    FreeNode(to_free);
 | 
	
		
			
				|  |  | +    gpr_free(to_free);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    gpr_mu_destroy(&tracer_mu_);
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -122,7 +121,7 @@ void ChannelTracer::AddTraceEventNode(TraceEvent* new_trace_node) {
 | 
	
		
			
				|  |  |    if (list_size_ > max_list_size_) {
 | 
	
		
			
				|  |  |      TraceEvent* to_free = head_trace_;
 | 
	
		
			
				|  |  |      head_trace_ = head_trace_->next_;
 | 
	
		
			
				|  |  | -    FreeNode(to_free);
 | 
	
		
			
				|  |  | +    gpr_free(to_free);
 | 
	
		
			
				|  |  |      --list_size_;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -130,11 +129,11 @@ void ChannelTracer::AddTraceEventNode(TraceEvent* new_trace_node) {
 | 
	
		
			
				|  |  |  void ChannelTracer::AddTrace(grpc_slice data, grpc_error* error,
 | 
	
		
			
				|  |  |                               grpc_connectivity_state connectivity_state,
 | 
	
		
			
				|  |  |                               RefCountedPtr<ChannelTracer> referenced_tracer) {
 | 
	
		
			
				|  |  | -  if (!max_list_size_) return;  // tracing is disabled if max_nodes == 0
 | 
	
		
			
				|  |  | +  if (max_list_size_ == 0) return;  // tracing is disabled if max_nodes == 0
 | 
	
		
			
				|  |  |    ++num_children_seen_;
 | 
	
		
			
				|  |  |    // create and fill up the new node
 | 
	
		
			
				|  |  |    AddTraceEventNode(
 | 
	
		
			
				|  |  | -      New<TraceEvent>(data, error, connectivity_state, referenced_tracer));
 | 
	
		
			
				|  |  | +      New<TraceEvent>(data, error, connectivity_state, std::move(referenced_tracer)));
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void ChannelTracer::AddTrace(grpc_slice data, grpc_error* error,
 | 
	
	
		
			
				|  | @@ -142,8 +141,10 @@ void ChannelTracer::AddTrace(grpc_slice data, grpc_error* error,
 | 
	
		
			
				|  |  |    AddTraceEventNode(New<TraceEvent>(data, error, connectivity_state));
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +namespace {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  // returns an allocated string that represents tm according to RFC-3339.
 | 
	
		
			
				|  |  | -static char* fmt_time(gpr_timespec tm) {
 | 
	
		
			
				|  |  | +char* fmt_time(gpr_timespec tm) {
 | 
	
		
			
				|  |  |    char buffer[35];
 | 
	
		
			
				|  |  |    struct tm* tm_info = localtime((const time_t*)&tm.tv_sec);
 | 
	
		
			
				|  |  |    strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%S", tm_info);
 | 
	
	
		
			
				|  | @@ -152,36 +153,7 @@ static char* fmt_time(gpr_timespec tm) {
 | 
	
		
			
				|  |  |    return full_time_str;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -// Helper class that is responsible for walking the tree of ChannelTracer
 | 
	
		
			
				|  |  | -// objects and rendering the trace as JSON according to:
 | 
	
		
			
				|  |  | -// https://github.com/grpc/proposal/pull/7
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// The rendered JSON should be of this format:
 | 
	
		
			
				|  |  | -// {
 | 
	
		
			
				|  |  | -//   "channelData": {
 | 
	
		
			
				|  |  | -//     "uuid": string,
 | 
	
		
			
				|  |  | -//     "numNodesLogged": number,
 | 
	
		
			
				|  |  | -//     "startTime": timestamp string,
 | 
	
		
			
				|  |  | -//     "nodes": [
 | 
	
		
			
				|  |  | -//       {
 | 
	
		
			
				|  |  | -//         "data": string,
 | 
	
		
			
				|  |  | -//         "error": string,
 | 
	
		
			
				|  |  | -//         "time": timestamp string,
 | 
	
		
			
				|  |  | -//         // can only be one of the states in connectivity_state.h
 | 
	
		
			
				|  |  | -//         "state": enum string,
 | 
	
		
			
				|  |  | -//         // uuid of referenced subchannel.
 | 
	
		
			
				|  |  | -//         // Optional, only present if this event refers to a child object.
 | 
	
		
			
				|  |  | -//         // and example of a referenced child would be a trace event for a
 | 
	
		
			
				|  |  | -//         // subchannel being created.
 | 
	
		
			
				|  |  | -//         "child_uuid": string
 | 
	
		
			
				|  |  | -//       },
 | 
	
		
			
				|  |  | -//     ]
 | 
	
		
			
				|  |  | -//   },
 | 
	
		
			
				|  |  | -//   // Optional, only present if this channel has children
 | 
	
		
			
				|  |  | -//   "childData": [
 | 
	
		
			
				|  |  | -//     // List of child data, which is of the exact same format as the
 | 
	
		
			
				|  |  | -//   ]
 | 
	
		
			
				|  |  | -// }
 | 
	
		
			
				|  |  | +} // anonymous namespace 
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  class ChannelTracerRenderer {
 | 
	
		
			
				|  |  |   public:
 | 
	
	
		
			
				|  | @@ -242,7 +214,6 @@ class ChannelTracerRenderer {
 | 
	
		
			
				|  |  |    // recursively populate each referenced child as it passes that node.
 | 
	
		
			
				|  |  |    void PopulateChannelData(grpc_json* channel_data, grpc_json* children) {
 | 
	
		
			
				|  |  |      grpc_json* child = nullptr;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      char* uuid_str;
 | 
	
		
			
				|  |  |      gpr_asprintf(&uuid_str, "%" PRIdPTR, current_tracer_->channel_uuid_);
 | 
	
		
			
				|  |  |      child = grpc_json_create_child(child, channel_data, "uuid", uuid_str,
 |