commit
f13288de48
118 changed files with 2227 additions and 603 deletions
@ -0,0 +1,238 @@ |
|||||||
|
/*
|
||||||
|
* |
||||||
|
* 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 <grpc/impl/codegen/port_platform.h> |
||||||
|
|
||||||
|
#include "src/core/lib/channel/channel_trace.h" |
||||||
|
|
||||||
|
#include <grpc/grpc.h> |
||||||
|
#include <grpc/support/alloc.h> |
||||||
|
#include <grpc/support/log.h> |
||||||
|
#include <grpc/support/string_util.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
|
||||||
|
#include "src/core/lib/channel/channel_trace_registry.h" |
||||||
|
#include "src/core/lib/channel/status_util.h" |
||||||
|
#include "src/core/lib/gpr/string.h" |
||||||
|
#include "src/core/lib/gpr/useful.h" |
||||||
|
#include "src/core/lib/gprpp/memory.h" |
||||||
|
#include "src/core/lib/iomgr/error.h" |
||||||
|
#include "src/core/lib/slice/slice_internal.h" |
||||||
|
#include "src/core/lib/surface/channel.h" |
||||||
|
#include "src/core/lib/transport/connectivity_state.h" |
||||||
|
#include "src/core/lib/transport/error_utils.h" |
||||||
|
|
||||||
|
namespace grpc_core { |
||||||
|
|
||||||
|
ChannelTrace::TraceEvent::TraceEvent( |
||||||
|
Severity severity, grpc_slice data, |
||||||
|
RefCountedPtr<ChannelTrace> referenced_tracer, ReferencedType type) |
||||||
|
: severity_(severity), |
||||||
|
data_(data), |
||||||
|
timestamp_(grpc_millis_to_timespec(grpc_core::ExecCtx::Get()->Now(), |
||||||
|
GPR_CLOCK_REALTIME)), |
||||||
|
next_(nullptr), |
||||||
|
referenced_tracer_(std::move(referenced_tracer)), |
||||||
|
referenced_type_(type) {} |
||||||
|
|
||||||
|
ChannelTrace::TraceEvent::TraceEvent(Severity severity, grpc_slice data) |
||||||
|
: severity_(severity), |
||||||
|
data_(data), |
||||||
|
timestamp_(grpc_millis_to_timespec(grpc_core::ExecCtx::Get()->Now(), |
||||||
|
GPR_CLOCK_REALTIME)), |
||||||
|
next_(nullptr) {} |
||||||
|
|
||||||
|
ChannelTrace::TraceEvent::~TraceEvent() { grpc_slice_unref_internal(data_); } |
||||||
|
|
||||||
|
ChannelTrace::ChannelTrace(size_t max_events) |
||||||
|
: channel_uuid_(-1), |
||||||
|
num_events_logged_(0), |
||||||
|
list_size_(0), |
||||||
|
max_list_size_(max_events), |
||||||
|
head_trace_(nullptr), |
||||||
|
tail_trace_(nullptr) { |
||||||
|
if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0
|
||||||
|
gpr_mu_init(&tracer_mu_); |
||||||
|
channel_uuid_ = grpc_channel_trace_registry_register_channel_trace(this); |
||||||
|
time_created_ = grpc_millis_to_timespec(grpc_core::ExecCtx::Get()->Now(), |
||||||
|
GPR_CLOCK_REALTIME); |
||||||
|
} |
||||||
|
|
||||||
|
ChannelTrace::~ChannelTrace() { |
||||||
|
if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0
|
||||||
|
TraceEvent* it = head_trace_; |
||||||
|
while (it != nullptr) { |
||||||
|
TraceEvent* to_free = it; |
||||||
|
it = it->next(); |
||||||
|
Delete<TraceEvent>(to_free); |
||||||
|
} |
||||||
|
grpc_channel_trace_registry_unregister_channel_trace(channel_uuid_); |
||||||
|
gpr_mu_destroy(&tracer_mu_); |
||||||
|
} |
||||||
|
|
||||||
|
intptr_t ChannelTrace::GetUuid() const { return channel_uuid_; } |
||||||
|
|
||||||
|
void ChannelTrace::AddTraceEventHelper(TraceEvent* new_trace_event) { |
||||||
|
++num_events_logged_; |
||||||
|
// first event case
|
||||||
|
if (head_trace_ == nullptr) { |
||||||
|
head_trace_ = tail_trace_ = new_trace_event; |
||||||
|
} |
||||||
|
// regular event add case
|
||||||
|
else { |
||||||
|
tail_trace_->set_next(new_trace_event); |
||||||
|
tail_trace_ = tail_trace_->next(); |
||||||
|
} |
||||||
|
++list_size_; |
||||||
|
// maybe garbage collect the end
|
||||||
|
if (list_size_ > max_list_size_) { |
||||||
|
TraceEvent* to_free = head_trace_; |
||||||
|
head_trace_ = head_trace_->next(); |
||||||
|
Delete<TraceEvent>(to_free); |
||||||
|
--list_size_; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void ChannelTrace::AddTraceEvent(Severity severity, grpc_slice data) { |
||||||
|
if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0
|
||||||
|
AddTraceEventHelper(New<TraceEvent>(severity, data)); |
||||||
|
} |
||||||
|
|
||||||
|
void ChannelTrace::AddTraceEventReferencingChannel( |
||||||
|
Severity severity, grpc_slice data, |
||||||
|
RefCountedPtr<ChannelTrace> referenced_tracer) { |
||||||
|
if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0
|
||||||
|
// create and fill up the new event
|
||||||
|
AddTraceEventHelper( |
||||||
|
New<TraceEvent>(severity, data, std::move(referenced_tracer), Channel)); |
||||||
|
} |
||||||
|
|
||||||
|
void ChannelTrace::AddTraceEventReferencingSubchannel( |
||||||
|
Severity severity, grpc_slice data, |
||||||
|
RefCountedPtr<ChannelTrace> referenced_tracer) { |
||||||
|
if (max_list_size_ == 0) return; // tracing is disabled if max_events == 0
|
||||||
|
// create and fill up the new event
|
||||||
|
AddTraceEventHelper(New<TraceEvent>( |
||||||
|
severity, data, std::move(referenced_tracer), Subchannel)); |
||||||
|
} |
||||||
|
|
||||||
|
namespace { |
||||||
|
|
||||||
|
// returns an allocated string that represents tm according to RFC-3339, and,
|
||||||
|
// more specifically, follows:
|
||||||
|
// https://developers.google.com/protocol-buffers/docs/proto3#json
|
||||||
|
//
|
||||||
|
// "Uses RFC 3339, where generated output will always be Z-normalized and uses
|
||||||
|
// 0, 3, 6 or 9 fractional digits."
|
||||||
|
char* fmt_time(gpr_timespec tm) { |
||||||
|
char time_buffer[35]; |
||||||
|
char ns_buffer[11]; // '.' + 9 digits of precision
|
||||||
|
struct tm* tm_info = localtime((const time_t*)&tm.tv_sec); |
||||||
|
strftime(time_buffer, sizeof(time_buffer), "%Y-%m-%dT%H:%M:%S", tm_info); |
||||||
|
snprintf(ns_buffer, 11, ".%09d", tm.tv_nsec); |
||||||
|
// This loop trims off trailing zeros by inserting a null character that the
|
||||||
|
// right point. We iterate in chunks of three because we want 0, 3, 6, or 9
|
||||||
|
// fractional digits.
|
||||||
|
for (int i = 7; i >= 1; i -= 3) { |
||||||
|
if (ns_buffer[i] == '0' && ns_buffer[i + 1] == '0' && |
||||||
|
ns_buffer[i + 2] == '0') { |
||||||
|
ns_buffer[i] = '\0'; |
||||||
|
// Edge case in which all fractional digits were 0.
|
||||||
|
if (i == 1) { |
||||||
|
ns_buffer[0] = '\0'; |
||||||
|
} |
||||||
|
} else { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
char* full_time_str; |
||||||
|
gpr_asprintf(&full_time_str, "%s%sZ", time_buffer, ns_buffer); |
||||||
|
return full_time_str; |
||||||
|
} |
||||||
|
|
||||||
|
const char* severity_string(ChannelTrace::Severity severity) { |
||||||
|
switch (severity) { |
||||||
|
case ChannelTrace::Severity::Info: |
||||||
|
return "CT_INFO"; |
||||||
|
case ChannelTrace::Severity::Warning: |
||||||
|
return "CT_WARNING"; |
||||||
|
case ChannelTrace::Severity::Error: |
||||||
|
return "CT_ERROR"; |
||||||
|
default: |
||||||
|
GPR_UNREACHABLE_CODE(return "CT_UNKNOWN"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
void ChannelTrace::TraceEvent::RenderTraceEvent(grpc_json* json) const { |
||||||
|
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); |
||||||
|
json_iterator = grpc_json_create_child(json_iterator, json, "severity", |
||||||
|
severity_string(severity_), |
||||||
|
GRPC_JSON_STRING, false); |
||||||
|
json_iterator = |
||||||
|
grpc_json_create_child(json_iterator, json, "timestamp", |
||||||
|
fmt_time(timestamp_), GRPC_JSON_STRING, true); |
||||||
|
if (referenced_tracer_ != nullptr) { |
||||||
|
char* uuid_str; |
||||||
|
gpr_asprintf(&uuid_str, "%" PRIdPTR, referenced_tracer_->channel_uuid_); |
||||||
|
grpc_json* child_ref = grpc_json_create_child( |
||||||
|
json_iterator, json, |
||||||
|
(referenced_type_ == Channel) ? "channelRef" : "subchannelRef", nullptr, |
||||||
|
GRPC_JSON_OBJECT, false); |
||||||
|
json_iterator = grpc_json_create_child( |
||||||
|
nullptr, child_ref, |
||||||
|
(referenced_type_ == Channel) ? "channelId" : "subchannelId", uuid_str, |
||||||
|
GRPC_JSON_STRING, true); |
||||||
|
json_iterator = child_ref; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
char* ChannelTrace::RenderTrace() const { |
||||||
|
if (!max_list_size_) |
||||||
|
return nullptr; // tracing is disabled if max_events == 0
|
||||||
|
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, "numEventsLogged", |
||||||
|
num_events_logged_str, GRPC_JSON_STRING, true); |
||||||
|
json_iterator = |
||||||
|
grpc_json_create_child(json_iterator, json, "creationTime", |
||||||
|
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
|
@ -0,0 +1,133 @@ |
|||||||
|
/*
|
||||||
|
* |
||||||
|
* 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_CHANNEL_CHANNEL_TRACE_H |
||||||
|
#define GRPC_CORE_LIB_CHANNEL_CHANNEL_TRACE_H |
||||||
|
|
||||||
|
#include <grpc/impl/codegen/port_platform.h> |
||||||
|
|
||||||
|
#include <grpc/grpc.h> |
||||||
|
#include "src/core/lib/gprpp/ref_counted.h" |
||||||
|
#include "src/core/lib/gprpp/ref_counted_ptr.h" |
||||||
|
#include "src/core/lib/iomgr/error.h" |
||||||
|
#include "src/core/lib/json/json.h" |
||||||
|
|
||||||
|
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
|
||||||
|
intptr_t GetUuid() const; |
||||||
|
|
||||||
|
enum Severity { |
||||||
|
Unset = 0, // never to be used
|
||||||
|
Info, // we start at 1 to avoid using proto default values
|
||||||
|
Warning, |
||||||
|
Error |
||||||
|
}; |
||||||
|
|
||||||
|
// Adds a new trace event to the tracing object
|
||||||
|
//
|
||||||
|
// TODO(ncteisen): as this call is used more and more throughout the gRPC
|
||||||
|
// stack, determine if it makes more sense to accept a char* instead of a
|
||||||
|
// slice.
|
||||||
|
void AddTraceEvent(Severity severity, grpc_slice data); |
||||||
|
|
||||||
|
// 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.
|
||||||
|
// TODO(ncteisen): as this call is used more and more throughout the gRPC
|
||||||
|
// stack, determine if it makes more sense to accept a char* instead of a
|
||||||
|
// slice.
|
||||||
|
void AddTraceEventReferencingChannel( |
||||||
|
Severity severity, grpc_slice data, |
||||||
|
RefCountedPtr<ChannelTrace> referenced_tracer); |
||||||
|
void AddTraceEventReferencingSubchannel( |
||||||
|
Severity severity, grpc_slice data, |
||||||
|
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.
|
||||||
|
char* RenderTrace() const; |
||||||
|
|
||||||
|
private: |
||||||
|
// Types of objects that can be references by trace events.
|
||||||
|
enum ReferencedType { Channel, Subchannel }; |
||||||
|
// 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(Severity severity, grpc_slice data, |
||||||
|
RefCountedPtr<ChannelTrace> referenced_tracer, |
||||||
|
ReferencedType type); |
||||||
|
|
||||||
|
// Constructor for a TraceEvent that does not reverence a different
|
||||||
|
// channel.
|
||||||
|
TraceEvent(Severity severity, grpc_slice data); |
||||||
|
|
||||||
|
~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) const; |
||||||
|
|
||||||
|
// set and get for the next_ pointer.
|
||||||
|
TraceEvent* next() const { return next_; } |
||||||
|
void set_next(TraceEvent* next) { next_ = next; } |
||||||
|
|
||||||
|
private: |
||||||
|
Severity severity_; |
||||||
|
grpc_slice data_; |
||||||
|
gpr_timespec timestamp_; |
||||||
|
TraceEvent* next_; |
||||||
|
// the tracer object for the (sub)channel that this trace event refers to.
|
||||||
|
RefCountedPtr<ChannelTrace> referenced_tracer_; |
||||||
|
// the type that the referenced tracer points to. Unused if this trace
|
||||||
|
// does not point to any channel or subchannel
|
||||||
|
ReferencedType referenced_type_; |
||||||
|
}; // TraceEvent
|
||||||
|
|
||||||
|
// Internal helper to add and link in a trace event
|
||||||
|
void AddTraceEventHelper(TraceEvent* new_trace_event); |
||||||
|
|
||||||
|
gpr_mu tracer_mu_; |
||||||
|
intptr_t channel_uuid_; |
||||||
|
uint64_t num_events_logged_; |
||||||
|
size_t list_size_; |
||||||
|
size_t max_list_size_; |
||||||
|
TraceEvent* head_trace_; |
||||||
|
TraceEvent* tail_trace_; |
||||||
|
gpr_timespec time_created_; |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace grpc_core
|
||||||
|
|
||||||
|
#endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_TRACE_H */ |
@ -0,0 +1,80 @@ |
|||||||
|
/*
|
||||||
|
* |
||||||
|
* 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 <grpc/impl/codegen/port_platform.h> |
||||||
|
|
||||||
|
#include "src/core/lib/avl/avl.h" |
||||||
|
#include "src/core/lib/channel/channel_trace.h" |
||||||
|
#include "src/core/lib/channel/channel_trace_registry.h" |
||||||
|
#include "src/core/lib/gpr/useful.h" |
||||||
|
|
||||||
|
#include <grpc/support/alloc.h> |
||||||
|
#include <grpc/support/log.h> |
||||||
|
|
||||||
|
// file global lock and avl.
|
||||||
|
static gpr_mu g_mu; |
||||||
|
static grpc_avl g_avl; |
||||||
|
static gpr_atm g_uuid = 0; |
||||||
|
|
||||||
|
// avl vtable for uuid (intptr_t) -> ChannelTrace
|
||||||
|
// this table is only looking, it does not own anything.
|
||||||
|
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 GPR_ICMP(key1, key2); |
||||||
|
} |
||||||
|
|
||||||
|
static void destroy_channel_trace(void* trace, void* user_data) {} |
||||||
|
static void* copy_channel_trace(void* trace, void* user_data) { return trace; } |
||||||
|
static const grpc_avl_vtable avl_vtable = { |
||||||
|
destroy_intptr, copy_intptr, compare_intptr, destroy_channel_trace, |
||||||
|
copy_channel_trace}; |
||||||
|
|
||||||
|
void grpc_channel_trace_registry_init() { |
||||||
|
gpr_mu_init(&g_mu); |
||||||
|
g_avl = grpc_avl_create(&avl_vtable); |
||||||
|
} |
||||||
|
|
||||||
|
void grpc_channel_trace_registry_shutdown() { |
||||||
|
grpc_avl_unref(g_avl, nullptr); |
||||||
|
gpr_mu_destroy(&g_mu); |
||||||
|
} |
||||||
|
|
||||||
|
intptr_t grpc_channel_trace_registry_register_channel_trace( |
||||||
|
grpc_core::ChannelTrace* channel_trace) { |
||||||
|
intptr_t prior = gpr_atm_no_barrier_fetch_add(&g_uuid, 1); |
||||||
|
gpr_mu_lock(&g_mu); |
||||||
|
g_avl = grpc_avl_add(g_avl, (void*)prior, channel_trace, nullptr); |
||||||
|
gpr_mu_unlock(&g_mu); |
||||||
|
return prior; |
||||||
|
} |
||||||
|
|
||||||
|
void grpc_channel_trace_registry_unregister_channel_trace(intptr_t uuid) { |
||||||
|
gpr_mu_lock(&g_mu); |
||||||
|
g_avl = grpc_avl_remove(g_avl, (void*)uuid, nullptr); |
||||||
|
gpr_mu_unlock(&g_mu); |
||||||
|
} |
||||||
|
|
||||||
|
grpc_core::ChannelTrace* grpc_channel_trace_registry_get_channel_trace( |
||||||
|
intptr_t uuid) { |
||||||
|
gpr_mu_lock(&g_mu); |
||||||
|
grpc_core::ChannelTrace* ret = static_cast<grpc_core::ChannelTrace*>( |
||||||
|
grpc_avl_get(g_avl, (void*)uuid, nullptr)); |
||||||
|
gpr_mu_unlock(&g_mu); |
||||||
|
return ret; |
||||||
|
} |
@ -0,0 +1,43 @@ |
|||||||
|
/*
|
||||||
|
* |
||||||
|
* 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_CHANNEL_CHANNEL_TRACE_REGISTRY_H |
||||||
|
#define GRPC_CORE_LIB_CHANNEL_CHANNEL_TRACE_REGISTRY_H |
||||||
|
|
||||||
|
#include <grpc/impl/codegen/port_platform.h> |
||||||
|
|
||||||
|
#include "src/core/lib/channel/channel_trace.h" |
||||||
|
|
||||||
|
#include <stdint.h> |
||||||
|
|
||||||
|
// TODO(ncteisen): convert this file to C++
|
||||||
|
|
||||||
|
void grpc_channel_trace_registry_init(); |
||||||
|
void grpc_channel_trace_registry_shutdown(); |
||||||
|
|
||||||
|
// globally registers a ChannelTrace. Returns its unique uuid
|
||||||
|
intptr_t grpc_channel_trace_registry_register_channel_trace( |
||||||
|
grpc_core::ChannelTrace* channel_trace); |
||||||
|
// globally unregisters the ChannelTrace that is associated to uuid.
|
||||||
|
void grpc_channel_trace_registry_unregister_channel_trace(intptr_t uuid); |
||||||
|
// if object with uuid has previously been registered, returns the ChannelTrace
|
||||||
|
// associated with that uuid. Else returns nullptr.
|
||||||
|
grpc_core::ChannelTrace* grpc_channel_trace_registry_get_channel_trace( |
||||||
|
intptr_t uuid); |
||||||
|
|
||||||
|
#endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_TRACE_REGISTRY_H */ |
@ -0,0 +1,26 @@ |
|||||||
|
# Copyright 2018 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. |
||||||
|
|
||||||
|
licenses(["notice"]) # Apache v2 |
||||||
|
|
||||||
|
load("//bazel:grpc_build_system.bzl", "grpc_proto_library", "grpc_package") |
||||||
|
|
||||||
|
grpc_package(name = "channelz", visibility = "public") |
||||||
|
|
||||||
|
grpc_proto_library( |
||||||
|
name = "channelz_proto", |
||||||
|
srcs = ["channelz.proto"], |
||||||
|
has_services = True, |
||||||
|
well_known_protos = True, |
||||||
|
) |
@ -0,0 +1,456 @@ |
|||||||
|
// Copyright 2018 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. |
||||||
|
|
||||||
|
syntax = "proto3"; |
||||||
|
|
||||||
|
package grpc.channelz; |
||||||
|
|
||||||
|
import "google/protobuf/any.proto"; |
||||||
|
import "google/protobuf/duration.proto"; |
||||||
|
import "google/protobuf/timestamp.proto"; |
||||||
|
import "google/protobuf/wrappers.proto"; |
||||||
|
|
||||||
|
// See go/grpc-channelz. |
||||||
|
|
||||||
|
// Channel is a logical grouping of channels, subchannels, and sockets. |
||||||
|
message Channel { |
||||||
|
// The identifier for this channel. |
||||||
|
ChannelRef ref = 1; |
||||||
|
// Data specific to this channel. |
||||||
|
ChannelData data = 2; |
||||||
|
// At most one of 'channel_ref+subchannel_ref' and 'socket' is set. |
||||||
|
|
||||||
|
// There are no ordering guarantees on the order of channel refs. |
||||||
|
// There may not be cycles in the ref graph. |
||||||
|
// A channel ref may be present in more than one channel or subchannel. |
||||||
|
repeated ChannelRef channel_ref = 3; |
||||||
|
|
||||||
|
// At most one of 'channel_ref+subchannel_ref' and 'socket' is set. |
||||||
|
// There are no ordering guarantees on the order of subchannel refs. |
||||||
|
// There may not be cycles in the ref graph. |
||||||
|
// A sub channel ref may be present in more than one channel or subchannel. |
||||||
|
repeated SubchannelRef subchannel_ref = 4; |
||||||
|
|
||||||
|
// There are no ordering guarantees on the order of sockets. |
||||||
|
repeated SocketRef socket = 5; |
||||||
|
} |
||||||
|
|
||||||
|
// Subchannel is a logical grouping of channels, subchannels, and sockets. |
||||||
|
// A subchannel is load balanced over by it's ancestor |
||||||
|
message Subchannel { |
||||||
|
// The identifier for this channel. |
||||||
|
SubchannelRef ref = 1; |
||||||
|
// Data specific to this channel. |
||||||
|
ChannelData data = 2; |
||||||
|
// At most one of 'channel_ref+subchannel_ref' and 'socket' is set. |
||||||
|
|
||||||
|
// There are no ordering guarantees on the order of channel refs. |
||||||
|
// There may not be cycles in the ref graph. |
||||||
|
// A channel ref may be present in more than one channel or subchannel. |
||||||
|
repeated ChannelRef channel_ref = 3; |
||||||
|
|
||||||
|
// At most one of 'channel_ref+subchannel_ref' and 'socket' is set. |
||||||
|
// There are no ordering guarantees on the order of subchannel refs. |
||||||
|
// There may not be cycles in the ref graph. |
||||||
|
// A sub channel ref may be present in more than one channel or subchannel. |
||||||
|
repeated SubchannelRef subchannel_ref = 4; |
||||||
|
|
||||||
|
// There are no ordering guarantees on the order of sockets. |
||||||
|
repeated SocketRef socket = 5; |
||||||
|
} |
||||||
|
|
||||||
|
// These come from the specified states in this document: |
||||||
|
// https://github.com/grpc/grpc/blob/master/doc/connectivity-semantics-and-api.md |
||||||
|
message ChannelConnectivityState { |
||||||
|
enum State { |
||||||
|
UNKNOWN = 0; |
||||||
|
IDLE = 1; |
||||||
|
CONNECTING = 2; |
||||||
|
READY = 3; |
||||||
|
TRANSIENT_FAILURE = 4; |
||||||
|
SHUTDOWN = 5; |
||||||
|
} |
||||||
|
State state = 1; |
||||||
|
} |
||||||
|
|
||||||
|
message ChannelData { |
||||||
|
|
||||||
|
ChannelConnectivityState state = 1; |
||||||
|
|
||||||
|
// The target this channel originally tried to connect to. May be absent |
||||||
|
string target = 2; |
||||||
|
|
||||||
|
ChannelTrace trace = 3; |
||||||
|
|
||||||
|
// The number of calls started on the channel |
||||||
|
int64 calls_started = 4; |
||||||
|
// The number of calls that have completed with an OK status |
||||||
|
int64 calls_succeeded = 5; |
||||||
|
// The number of calls that have a completed with a non-OK status |
||||||
|
int64 calls_failed = 6; |
||||||
|
|
||||||
|
// The last time a call was started on the channel. |
||||||
|
google.protobuf.Timestamp last_call_started_timestamp = 7; |
||||||
|
} |
||||||
|
|
||||||
|
// A trace event is an interesting thing that happened to a channel or |
||||||
|
// subchannel, such as creation, address resolution, subchannel creation, etc. |
||||||
|
message ChannelTraceEvent { |
||||||
|
// High level description of the event. |
||||||
|
string description = 1; |
||||||
|
// The supported severity levels of trace events. |
||||||
|
enum Severity { |
||||||
|
CT_UNKNOWN = 0; |
||||||
|
CT_INFO = 1; |
||||||
|
CT_WARNING = 2; |
||||||
|
CT_ERROR = 3; |
||||||
|
} |
||||||
|
// the severity of the trace event |
||||||
|
Severity severity = 2; |
||||||
|
// When this event occurred. |
||||||
|
google.protobuf.Timestamp timestamp = 3; |
||||||
|
// ref of referenced channel or subchannel. |
||||||
|
// Optional, only present if this event refers to a child object. For example, |
||||||
|
// this field would be filled if this trace event was for a subchannel being |
||||||
|
// created. |
||||||
|
oneof child_ref { |
||||||
|
ChannelRef channel_ref = 4; |
||||||
|
SubchannelRef subchannel_ref = 5; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
message ChannelTrace { |
||||||
|
// Number of events ever logged in this tracing object. This can differ from |
||||||
|
// events.size() because events can be overwritten or garbage collected by |
||||||
|
// implementations. |
||||||
|
int64 num_events_logged = 1; |
||||||
|
// Time that this channel was created. |
||||||
|
google.protobuf.Timestamp creation_time = 2; |
||||||
|
// List of events that have occurred on this channel. |
||||||
|
repeated ChannelTraceEvent events = 3; |
||||||
|
} |
||||||
|
|
||||||
|
message ChannelRef { |
||||||
|
// The globally unique id for this channel. Must be a positive number. |
||||||
|
int64 channel_id = 1; |
||||||
|
// An optional name associated with the channel. |
||||||
|
string name = 2; |
||||||
|
// Intentionally don't use field numbers from other refs. |
||||||
|
reserved 3, 4, 5, 6; |
||||||
|
} |
||||||
|
|
||||||
|
message SubchannelRef { |
||||||
|
// The globally unique id for this subchannel. Must be a positive number. |
||||||
|
int64 subchannel_id = 7; |
||||||
|
// An optional name associated with the subchannel. |
||||||
|
string name = 8; |
||||||
|
// Intentionally don't use field numbers from other refs. |
||||||
|
reserved 1, 2, 3, 4, 5, 6; |
||||||
|
} |
||||||
|
|
||||||
|
message SocketRef { |
||||||
|
int64 socket_id = 3; |
||||||
|
// An optional name associated with the socket. |
||||||
|
string name = 4; |
||||||
|
// Intentionally don't use field numbers from other refs. |
||||||
|
reserved 1, 2, 5, 6, 7, 8; |
||||||
|
} |
||||||
|
|
||||||
|
message ServerRef { |
||||||
|
// A globally unique identifier for this server. Must be a positive number. |
||||||
|
int64 server_id = 5; |
||||||
|
// An optional name associated with the server. |
||||||
|
string name = 6; |
||||||
|
// Intentionally don't use field numbers from other refs. |
||||||
|
reserved 1, 2, 3, 4, 7, 8; |
||||||
|
} |
||||||
|
|
||||||
|
message Server { |
||||||
|
ServerRef ref = 1; |
||||||
|
ServerData data = 2; |
||||||
|
|
||||||
|
// The sockets that the server is listening on. There are no ordering |
||||||
|
// guarantees. |
||||||
|
repeated SocketRef listen_socket = 3; |
||||||
|
} |
||||||
|
|
||||||
|
message ServerData { |
||||||
|
ChannelTrace trace = 1; |
||||||
|
|
||||||
|
// The number of incoming calls started on the server |
||||||
|
int64 calls_started = 2; |
||||||
|
// The number of incoming calls that have completed with an OK status |
||||||
|
int64 calls_succeeded = 3; |
||||||
|
// The number of incoming calls that have a completed with a non-OK status |
||||||
|
int64 calls_failed = 4; |
||||||
|
|
||||||
|
// The last time a call was started on the server. |
||||||
|
google.protobuf.Timestamp last_call_started_timestamp = 5; |
||||||
|
} |
||||||
|
|
||||||
|
// Information about an actual connection. Pronounced "sock-ay". |
||||||
|
message Socket { |
||||||
|
SocketRef ref = 1; |
||||||
|
|
||||||
|
SocketData data = 2; |
||||||
|
// The locally bound address. |
||||||
|
Address local = 3; |
||||||
|
// The remote bound address. May be absent. |
||||||
|
Address remote = 4; |
||||||
|
Security security = 5; |
||||||
|
|
||||||
|
// Optional, represents the name of the remote endpoint, if different than |
||||||
|
// the original target name. |
||||||
|
string remote_name = 6; |
||||||
|
} |
||||||
|
|
||||||
|
message SocketData { |
||||||
|
// The number of streams that have been started. |
||||||
|
int64 streams_started = 1; |
||||||
|
// The number of streams that have ended successfully with the EoS bit set for |
||||||
|
// both end points |
||||||
|
int64 streams_succeeded = 2; |
||||||
|
// The number of incoming streams that have a completed with a non-OK status |
||||||
|
int64 streams_failed = 3; |
||||||
|
|
||||||
|
// The number of messages successfully sent on this socket. |
||||||
|
int64 messages_sent = 4; |
||||||
|
int64 messages_received = 5; |
||||||
|
|
||||||
|
// The number of keep alives sent. This is typically implemented with HTTP/2 |
||||||
|
// ping messages. |
||||||
|
int64 keep_alives_sent = 6; |
||||||
|
|
||||||
|
// The last time a stream was created by this endpoint. Usually unset for |
||||||
|
// servers. |
||||||
|
google.protobuf.Timestamp last_local_stream_created_timestamp = 7; |
||||||
|
// The last time a stream was created by the remote endpoint. Usually unset |
||||||
|
// for clients. |
||||||
|
google.protobuf.Timestamp last_remote_stream_created_timestamp = 8; |
||||||
|
|
||||||
|
// The last time a message was sent by this endpoint. |
||||||
|
google.protobuf.Timestamp last_message_sent_timestamp = 9; |
||||||
|
// The last time a message was received by this endpoint. |
||||||
|
google.protobuf.Timestamp last_message_received_timestamp = 10; |
||||||
|
|
||||||
|
// The amount of window, granted to the local endpoint by the remote endpoint. |
||||||
|
// This may be slightly out of date due to network latency. This does NOT |
||||||
|
// include stream level or TCP level flow control info. |
||||||
|
google.protobuf.Int64Value local_flow_control_window = 11; |
||||||
|
|
||||||
|
// The amount of window, granted to the remote endpoint by the local endpoint. |
||||||
|
// This may be slightly out of date due to network latency. This does NOT |
||||||
|
// include stream level or TCP level flow control info. |
||||||
|
google.protobuf.Int64Value remote_flow_control_window = 12; |
||||||
|
|
||||||
|
repeated SocketOption option = 13; |
||||||
|
} |
||||||
|
|
||||||
|
message Address { |
||||||
|
message TcpIpAddress { |
||||||
|
// Either the IPv4 or IPv6 address in bytes. Will either be 4 bytes or 16 |
||||||
|
// bytes in length. |
||||||
|
bytes ip_address = 1; |
||||||
|
// 0-64k, or -1 if not appropriate. |
||||||
|
int32 port = 2; |
||||||
|
} |
||||||
|
// A Unix Domain Socket address. |
||||||
|
message UdsAddress { |
||||||
|
string filename = 1; |
||||||
|
} |
||||||
|
// An address type not included above. |
||||||
|
message OtherAddress { |
||||||
|
// The human readable version of the value. |
||||||
|
string name = 1; |
||||||
|
// The actual address message. |
||||||
|
google.protobuf.Any value = 2; |
||||||
|
} |
||||||
|
|
||||||
|
oneof address { |
||||||
|
TcpIpAddress tcpip_address = 1; |
||||||
|
UdsAddress uds_address = 2; |
||||||
|
OtherAddress other_address = 3; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
message Security { |
||||||
|
message Tls { |
||||||
|
// The key exchange used. e.g. X25519 |
||||||
|
string key_exchange = 1; |
||||||
|
// The cipher used. e.g. AES_128_GCM. |
||||||
|
string cipher = 2; |
||||||
|
// the certificate used by this endpoint. |
||||||
|
bytes local_certificate = 3; |
||||||
|
// the certificate used by the remote endpoint. |
||||||
|
bytes remote_certificate = 4; |
||||||
|
} |
||||||
|
message OtherSecurity { |
||||||
|
// The human readable version of the value. |
||||||
|
string name = 1; |
||||||
|
// The actual security details message. |
||||||
|
google.protobuf.Any value = 2; |
||||||
|
} |
||||||
|
oneof model { |
||||||
|
Tls tls = 1; |
||||||
|
OtherSecurity other = 2; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
message SocketOption { |
||||||
|
string name = 1; |
||||||
|
// The human readable value of this socket option. At least one of value or |
||||||
|
// additional will be set. |
||||||
|
string value = 2; |
||||||
|
// Additional data associated with the socket option. At least one of value |
||||||
|
// or additional will be set. |
||||||
|
google.protobuf.Any additional = 3; |
||||||
|
} |
||||||
|
|
||||||
|
// For use with SocketOption's additional field. This is primarily used for |
||||||
|
// SO_RCVTIMEO and SO_SNDTIMEO |
||||||
|
message SocketOptionTimeout { |
||||||
|
google.protobuf.Duration duration = 1; |
||||||
|
} |
||||||
|
|
||||||
|
message SocketOptionLinger { |
||||||
|
bool active = 1; |
||||||
|
google.protobuf.Duration duration = 2; |
||||||
|
} |
||||||
|
|
||||||
|
// Tcp info for SOL_TCP, TCP_INFO |
||||||
|
message SocketOptionTcpInfo { |
||||||
|
uint32 tcpi_state = 1; |
||||||
|
|
||||||
|
uint32 tcpi_ca_state = 2; |
||||||
|
uint32 tcpi_retransmits = 3; |
||||||
|
uint32 tcpi_probes = 4; |
||||||
|
uint32 tcpi_backoff = 5; |
||||||
|
uint32 tcpi_options = 6; |
||||||
|
uint32 tcpi_snd_wscale = 7; |
||||||
|
uint32 tcpi_rcv_wscale = 8; |
||||||
|
|
||||||
|
uint32 tcpi_rto = 9; |
||||||
|
uint32 tcpi_ato = 10; |
||||||
|
uint32 tcpi_snd_mss = 11; |
||||||
|
uint32 tcpi_rcv_mss = 12; |
||||||
|
|
||||||
|
uint32 tcpi_unacked = 13; |
||||||
|
uint32 tcpi_sacked = 14; |
||||||
|
uint32 tcpi_lost = 15; |
||||||
|
uint32 tcpi_retrans = 16; |
||||||
|
uint32 tcpi_fackets = 17; |
||||||
|
|
||||||
|
uint32 tcpi_last_data_sent = 18; |
||||||
|
uint32 tcpi_last_ack_sent = 19; |
||||||
|
uint32 tcpi_last_data_recv = 20; |
||||||
|
uint32 tcpi_last_ack_recv = 21; |
||||||
|
|
||||||
|
uint32 tcpi_pmtu = 22; |
||||||
|
uint32 tcpi_rcv_ssthresh = 23; |
||||||
|
uint32 tcpi_rtt = 24; |
||||||
|
uint32 tcpi_rttvar = 25; |
||||||
|
uint32 tcpi_snd_ssthresh = 26; |
||||||
|
uint32 tcpi_snd_cwnd = 27; |
||||||
|
uint32 tcpi_advmss = 28; |
||||||
|
uint32 tcpi_reordering = 29; |
||||||
|
} |
||||||
|
|
||||||
|
service Channelz { |
||||||
|
// Gets all root channels (e.g. channels the application has directly |
||||||
|
// created). This does not include subchannels nor non-top level channels. |
||||||
|
rpc GetTopChannels(GetTopChannelsRequest) returns (GetTopChannelsResponse); |
||||||
|
// Gets all servers that exist in the process. |
||||||
|
rpc GetServers(GetServersRequest) returns (GetServersResponse); |
||||||
|
// Gets all server sockets that exist in the process. |
||||||
|
rpc GetServerSockets(GetServerSocketsRequest) returns (GetServerSocketsResponse); |
||||||
|
// Returns a single Channel, or else a NOT_FOUND code. |
||||||
|
rpc GetChannel(GetChannelRequest) returns (GetChannelResponse); |
||||||
|
// Returns a single Subchannel, or else a NOT_FOUND code. |
||||||
|
rpc GetSubchannel(GetSubchannelRequest) returns (GetSubchannelResponse); |
||||||
|
// Returns a single Socket or else a NOT_FOUND code. |
||||||
|
rpc GetSocket(GetSocketRequest) returns (GetSocketResponse); |
||||||
|
} |
||||||
|
|
||||||
|
message GetServersRequest { |
||||||
|
// start_server_id indicates that only servers at or above this id should be |
||||||
|
// included in the results. |
||||||
|
int64 start_server_id = 1; |
||||||
|
} |
||||||
|
|
||||||
|
message GetServersResponse { |
||||||
|
// list of servers that the connection detail service knows about. Sorted in |
||||||
|
// ascending server_id order. |
||||||
|
repeated Server server = 1; |
||||||
|
// If set, indicates that the list of servers is the final list. Requesting |
||||||
|
// more servers will only return more if they are created after this RPC |
||||||
|
// completes. |
||||||
|
bool end = 2; |
||||||
|
} |
||||||
|
|
||||||
|
message GetServerSocketsRequest { |
||||||
|
int64 server_id = 1; |
||||||
|
// start_socket_id indicates that only sockets at or above this id should be |
||||||
|
// included in the results. |
||||||
|
int64 start_socket_id = 2; |
||||||
|
} |
||||||
|
|
||||||
|
message GetServerSocketsResponse { |
||||||
|
// list of socket refs that the connection detail service knows about. Sorted in |
||||||
|
// ascending socket_id order. |
||||||
|
repeated SocketRef socket_ref = 1; |
||||||
|
// If set, indicates that the list of sockets is the final list. Requesting |
||||||
|
// more sockets will only return more if they are created after this RPC |
||||||
|
// completes. |
||||||
|
bool end = 2; |
||||||
|
} |
||||||
|
|
||||||
|
message GetTopChannelsRequest { |
||||||
|
// start_channel_id indicates that only channels at or above this id should be |
||||||
|
// included in the results. |
||||||
|
int64 start_channel_id = 1; |
||||||
|
} |
||||||
|
|
||||||
|
message GetTopChannelsResponse { |
||||||
|
// list of channels that the connection detail service knows about. Sorted in |
||||||
|
// ascending channel_id order. |
||||||
|
repeated Channel channel = 1; |
||||||
|
// If set, indicates that the list of channels is the final list. Requesting |
||||||
|
// more channels can only return more if they are created after this RPC |
||||||
|
// completes. |
||||||
|
bool end = 2; |
||||||
|
} |
||||||
|
|
||||||
|
message GetChannelRequest { |
||||||
|
int64 channel_id = 1; |
||||||
|
} |
||||||
|
|
||||||
|
message GetChannelResponse { |
||||||
|
Channel channel = 1; |
||||||
|
} |
||||||
|
|
||||||
|
message GetSubchannelRequest { |
||||||
|
int64 subchannel_id = 1; |
||||||
|
} |
||||||
|
|
||||||
|
message GetSubchannelResponse { |
||||||
|
Subchannel subchannel = 1; |
||||||
|
} |
||||||
|
|
||||||
|
message GetSocketRequest { |
||||||
|
int64 socket_id = 1; |
||||||
|
} |
||||||
|
|
||||||
|
message GetSocketResponse { |
||||||
|
Socket socket = 1; |
||||||
|
} |
@ -0,0 +1,240 @@ |
|||||||
|
/*
|
||||||
|
* |
||||||
|
* 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 <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
|
||||||
|
#include <gtest/gtest.h> |
||||||
|
|
||||||
|
#include <grpc/support/alloc.h> |
||||||
|
#include <grpc/support/log.h> |
||||||
|
|
||||||
|
#include "src/core/lib/channel/channel_trace.h" |
||||||
|
#include "src/core/lib/channel/channel_trace_registry.h" |
||||||
|
#include "src/core/lib/gpr/useful.h" |
||||||
|
#include "src/core/lib/iomgr/exec_ctx.h" |
||||||
|
#include "src/core/lib/json/json.h" |
||||||
|
|
||||||
|
#include "test/core/util/test_config.h" |
||||||
|
#include "test/cpp/util/channel_trace_proto_helper.h" |
||||||
|
|
||||||
|
// remove me
|
||||||
|
#include <grpc/support/string_util.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
|
||||||
|
namespace grpc_core { |
||||||
|
namespace testing { |
||||||
|
namespace { |
||||||
|
|
||||||
|
grpc_json* GetJsonChild(grpc_json* parent, const char* key) { |
||||||
|
EXPECT_NE(parent, nullptr); |
||||||
|
for (grpc_json* child = parent->child; child != nullptr; |
||||||
|
child = child->next) { |
||||||
|
if (child->key != nullptr && strcmp(child->key, key) == 0) return child; |
||||||
|
} |
||||||
|
return nullptr; |
||||||
|
} |
||||||
|
|
||||||
|
void ValidateJsonArraySize(grpc_json* json, const char* key, |
||||||
|
size_t expected_size) { |
||||||
|
grpc_json* arr = GetJsonChild(json, key); |
||||||
|
ASSERT_NE(arr, nullptr); |
||||||
|
ASSERT_EQ(arr->type, GRPC_JSON_ARRAY); |
||||||
|
size_t count = 0; |
||||||
|
for (grpc_json* child = arr->child; child != nullptr; child = child->next) { |
||||||
|
++count; |
||||||
|
} |
||||||
|
ASSERT_EQ(count, expected_size); |
||||||
|
} |
||||||
|
|
||||||
|
void ValidateChannelTraceData(grpc_json* json, |
||||||
|
size_t num_events_logged_expected, |
||||||
|
size_t actual_num_events_expected) { |
||||||
|
ASSERT_NE(json, nullptr); |
||||||
|
grpc_json* num_events_logged_json = GetJsonChild(json, "numEventsLogged"); |
||||||
|
ASSERT_NE(num_events_logged_json, nullptr); |
||||||
|
grpc_json* start_time = GetJsonChild(json, "creationTime"); |
||||||
|
ASSERT_NE(start_time, nullptr); |
||||||
|
size_t num_events_logged = |
||||||
|
(size_t)strtol(num_events_logged_json->value, nullptr, 0); |
||||||
|
ASSERT_EQ(num_events_logged, num_events_logged_expected); |
||||||
|
ValidateJsonArraySize(json, "events", actual_num_events_expected); |
||||||
|
} |
||||||
|
|
||||||
|
void AddSimpleTrace(RefCountedPtr<ChannelTrace> tracer) { |
||||||
|
tracer->AddTraceEvent(ChannelTrace::Severity::Info, |
||||||
|
grpc_slice_from_static_string("simple trace")); |
||||||
|
} |
||||||
|
|
||||||
|
// checks for the existence of all the required members of the tracer.
|
||||||
|
void ValidateChannelTrace(RefCountedPtr<ChannelTrace> tracer, |
||||||
|
size_t expected_num_event_logged, size_t max_nodes) { |
||||||
|
if (!max_nodes) return; |
||||||
|
char* json_str = tracer->RenderTrace(); |
||||||
|
grpc::testing::ValidateChannelTraceProtoJsonTranslation(json_str); |
||||||
|
grpc_json* json = grpc_json_parse_string(json_str); |
||||||
|
ValidateChannelTraceData(json, expected_num_event_logged, |
||||||
|
GPR_MIN(expected_num_event_logged, max_nodes)); |
||||||
|
grpc_json_destroy(json); |
||||||
|
gpr_free(json_str); |
||||||
|
} |
||||||
|
|
||||||
|
void ValidateTraceDataMatchedUuidLookup(RefCountedPtr<ChannelTrace> tracer) { |
||||||
|
intptr_t uuid = tracer->GetUuid(); |
||||||
|
if (uuid == -1) return; // Doesn't make sense to lookup if tracing disabled
|
||||||
|
char* tracer_json_str = tracer->RenderTrace(); |
||||||
|
ChannelTrace* uuid_lookup = |
||||||
|
grpc_channel_trace_registry_get_channel_trace(uuid); |
||||||
|
char* uuid_lookup_json_str = uuid_lookup->RenderTrace(); |
||||||
|
EXPECT_EQ(strcmp(tracer_json_str, uuid_lookup_json_str), 0); |
||||||
|
gpr_free(tracer_json_str); |
||||||
|
gpr_free(uuid_lookup_json_str); |
||||||
|
} |
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
class ChannelTracerTest : public ::testing::TestWithParam<size_t> {}; |
||||||
|
|
||||||
|
// Tests basic ChannelTrace functionality like construction, adding trace, and
|
||||||
|
// lookups by uuid.
|
||||||
|
TEST_P(ChannelTracerTest, BasicTest) { |
||||||
|
grpc_core::ExecCtx exec_ctx; |
||||||
|
RefCountedPtr<ChannelTrace> tracer = MakeRefCounted<ChannelTrace>(GetParam()); |
||||||
|
AddSimpleTrace(tracer); |
||||||
|
AddSimpleTrace(tracer); |
||||||
|
ValidateTraceDataMatchedUuidLookup(tracer); |
||||||
|
tracer->AddTraceEvent(ChannelTrace::Severity::Info, |
||||||
|
grpc_slice_from_static_string("trace three")); |
||||||
|
tracer->AddTraceEvent(ChannelTrace::Severity::Error, |
||||||
|
grpc_slice_from_static_string("trace four error")); |
||||||
|
ValidateChannelTrace(tracer, 4, GetParam()); |
||||||
|
AddSimpleTrace(tracer); |
||||||
|
AddSimpleTrace(tracer); |
||||||
|
ValidateChannelTrace(tracer, 6, GetParam()); |
||||||
|
AddSimpleTrace(tracer); |
||||||
|
AddSimpleTrace(tracer); |
||||||
|
AddSimpleTrace(tracer); |
||||||
|
AddSimpleTrace(tracer); |
||||||
|
ValidateChannelTrace(tracer, 10, GetParam()); |
||||||
|
ValidateTraceDataMatchedUuidLookup(tracer); |
||||||
|
tracer.reset(nullptr); |
||||||
|
} |
||||||
|
|
||||||
|
// Tests more complex functionality, like a parent channel tracking
|
||||||
|
// subchannles. This exercises the ref/unref patterns since the parent tracer
|
||||||
|
// and this function will both hold refs to the subchannel.
|
||||||
|
TEST_P(ChannelTracerTest, ComplexTest) { |
||||||
|
grpc_core::ExecCtx exec_ctx; |
||||||
|
RefCountedPtr<ChannelTrace> tracer = MakeRefCounted<ChannelTrace>(GetParam()); |
||||||
|
AddSimpleTrace(tracer); |
||||||
|
AddSimpleTrace(tracer); |
||||||
|
RefCountedPtr<ChannelTrace> sc1 = MakeRefCounted<ChannelTrace>(GetParam()); |
||||||
|
tracer->AddTraceEventReferencingSubchannel( |
||||||
|
ChannelTrace::Severity::Info, |
||||||
|
grpc_slice_from_static_string("subchannel one created"), sc1); |
||||||
|
ValidateChannelTrace(tracer, 3, GetParam()); |
||||||
|
AddSimpleTrace(sc1); |
||||||
|
AddSimpleTrace(sc1); |
||||||
|
AddSimpleTrace(sc1); |
||||||
|
ValidateChannelTrace(sc1, 3, GetParam()); |
||||||
|
AddSimpleTrace(sc1); |
||||||
|
AddSimpleTrace(sc1); |
||||||
|
AddSimpleTrace(sc1); |
||||||
|
ValidateChannelTrace(sc1, 6, GetParam()); |
||||||
|
AddSimpleTrace(tracer); |
||||||
|
AddSimpleTrace(tracer); |
||||||
|
ValidateChannelTrace(tracer, 5, GetParam()); |
||||||
|
ValidateTraceDataMatchedUuidLookup(tracer); |
||||||
|
RefCountedPtr<ChannelTrace> sc2 = MakeRefCounted<ChannelTrace>(GetParam()); |
||||||
|
tracer->AddTraceEventReferencingChannel( |
||||||
|
ChannelTrace::Severity::Info, |
||||||
|
grpc_slice_from_static_string("LB channel two created"), sc2); |
||||||
|
tracer->AddTraceEventReferencingSubchannel( |
||||||
|
ChannelTrace::Severity::Warning, |
||||||
|
grpc_slice_from_static_string("subchannel one inactive"), sc1); |
||||||
|
ValidateChannelTrace(tracer, 7, GetParam()); |
||||||
|
AddSimpleTrace(tracer); |
||||||
|
AddSimpleTrace(tracer); |
||||||
|
AddSimpleTrace(tracer); |
||||||
|
AddSimpleTrace(tracer); |
||||||
|
AddSimpleTrace(tracer); |
||||||
|
AddSimpleTrace(tracer); |
||||||
|
ValidateTraceDataMatchedUuidLookup(tracer); |
||||||
|
tracer.reset(nullptr); |
||||||
|
sc1.reset(nullptr); |
||||||
|
sc2.reset(nullptr); |
||||||
|
} |
||||||
|
|
||||||
|
// Test a case in which the parent channel has subchannels and the subchannels
|
||||||
|
// have connections. Ensures that everything lives as long as it should then
|
||||||
|
// gets deleted.
|
||||||
|
TEST_P(ChannelTracerTest, TestNesting) { |
||||||
|
grpc_core::ExecCtx exec_ctx; |
||||||
|
RefCountedPtr<ChannelTrace> tracer = MakeRefCounted<ChannelTrace>(GetParam()); |
||||||
|
AddSimpleTrace(tracer); |
||||||
|
AddSimpleTrace(tracer); |
||||||
|
ValidateChannelTrace(tracer, 2, GetParam()); |
||||||
|
RefCountedPtr<ChannelTrace> sc1 = MakeRefCounted<ChannelTrace>(GetParam()); |
||||||
|
tracer->AddTraceEventReferencingChannel( |
||||||
|
ChannelTrace::Severity::Info, |
||||||
|
grpc_slice_from_static_string("subchannel one created"), sc1); |
||||||
|
ValidateChannelTrace(tracer, 3, GetParam()); |
||||||
|
AddSimpleTrace(sc1); |
||||||
|
RefCountedPtr<ChannelTrace> conn1 = MakeRefCounted<ChannelTrace>(GetParam()); |
||||||
|
// nesting one level deeper.
|
||||||
|
sc1->AddTraceEventReferencingSubchannel( |
||||||
|
ChannelTrace::Severity::Info, |
||||||
|
grpc_slice_from_static_string("connection one created"), conn1); |
||||||
|
ValidateChannelTrace(tracer, 3, GetParam()); |
||||||
|
AddSimpleTrace(conn1); |
||||||
|
AddSimpleTrace(tracer); |
||||||
|
AddSimpleTrace(tracer); |
||||||
|
ValidateChannelTrace(tracer, 5, GetParam()); |
||||||
|
ValidateChannelTrace(conn1, 1, GetParam()); |
||||||
|
RefCountedPtr<ChannelTrace> sc2 = MakeRefCounted<ChannelTrace>(GetParam()); |
||||||
|
tracer->AddTraceEventReferencingSubchannel( |
||||||
|
ChannelTrace::Severity::Info, |
||||||
|
grpc_slice_from_static_string("subchannel two created"), sc2); |
||||||
|
// this trace should not get added to the parents children since it is already
|
||||||
|
// present in the tracer.
|
||||||
|
tracer->AddTraceEventReferencingChannel( |
||||||
|
ChannelTrace::Severity::Warning, |
||||||
|
grpc_slice_from_static_string("subchannel one inactive"), sc1); |
||||||
|
AddSimpleTrace(tracer); |
||||||
|
ValidateChannelTrace(tracer, 8, GetParam()); |
||||||
|
tracer.reset(nullptr); |
||||||
|
sc1.reset(nullptr); |
||||||
|
sc2.reset(nullptr); |
||||||
|
conn1.reset(nullptr); |
||||||
|
} |
||||||
|
|
||||||
|
INSTANTIATE_TEST_CASE_P(ChannelTracerTestSweep, ChannelTracerTest, |
||||||
|
::testing::Values(0, 1, 2, 6, 10, 15)); |
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
} // namespace grpc_core
|
||||||
|
|
||||||
|
int main(int argc, char** argv) { |
||||||
|
grpc_test_init(argc, argv); |
||||||
|
grpc_init(); |
||||||
|
::testing::InitGoogleTest(&argc, argv); |
||||||
|
int ret = RUN_ALL_TESTS(); |
||||||
|
grpc_shutdown(); |
||||||
|
return ret; |
||||||
|
} |
@ -0,0 +1,56 @@ |
|||||||
|
/*
|
||||||
|
* |
||||||
|
* Copyright 2018 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 "test/cpp/util/channel_trace_proto_helper.h" |
||||||
|
|
||||||
|
#include <google/protobuf/text_format.h> |
||||||
|
#include <google/protobuf/util/json_util.h> |
||||||
|
|
||||||
|
#include <grpc/grpc.h> |
||||||
|
#include <grpc/support/log.h> |
||||||
|
#include <gtest/gtest.h> |
||||||
|
|
||||||
|
#include "src/proto/grpc/channelz/channelz.pb.h" |
||||||
|
|
||||||
|
namespace grpc { |
||||||
|
namespace testing { |
||||||
|
|
||||||
|
void ValidateChannelTraceProtoJsonTranslation(char* tracer_json_c_str) { |
||||||
|
std::string tracer_json_str(tracer_json_c_str); |
||||||
|
grpc::channelz::ChannelTrace channel_trace; |
||||||
|
google::protobuf::util::JsonParseOptions parse_options; |
||||||
|
// If the following line is failing, then uncomment the last line of the
|
||||||
|
// comment, and uncomment the lines that print the two strings. You can
|
||||||
|
// then compare the output, and determine what fields are missing.
|
||||||
|
//
|
||||||
|
// options.ignore_unknown_fields = true;
|
||||||
|
ASSERT_EQ(google::protobuf::util::JsonStringToMessage( |
||||||
|
tracer_json_str, &channel_trace, parse_options), |
||||||
|
google::protobuf::util::Status::OK); |
||||||
|
std::string proto_json_str; |
||||||
|
ASSERT_EQ(google::protobuf::util::MessageToJsonString(channel_trace, |
||||||
|
&proto_json_str), |
||||||
|
google::protobuf::util::Status::OK); |
||||||
|
// uncomment these to compare the the json strings.
|
||||||
|
// gpr_log(GPR_ERROR, "tracer json: %s", tracer_json_str.c_str());
|
||||||
|
// gpr_log(GPR_ERROR, "proto json: %s", proto_json_str.c_str());
|
||||||
|
ASSERT_EQ(tracer_json_str, proto_json_str); |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
} // namespace grpc
|
@ -0,0 +1,30 @@ |
|||||||
|
/*
|
||||||
|
* |
||||||
|
* Copyright 2018 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_TEST_CPP_UTIL_CHANNEL_TRACE_PROTO_HELPER_H |
||||||
|
#define GRPC_TEST_CPP_UTIL_CHANNEL_TRACE_PROTO_HELPER_H |
||||||
|
|
||||||
|
namespace grpc { |
||||||
|
namespace testing { |
||||||
|
|
||||||
|
void ValidateChannelTraceProtoJsonTranslation(char* tracer_json_c_str); |
||||||
|
|
||||||
|
} // namespace testing
|
||||||
|
} // namespace grpc
|
||||||
|
|
||||||
|
#endif // GRPC_TEST_CPP_UTIL_CHANNEL_TRACE_PROTO_HELPER_H
|
@ -1,62 +0,0 @@ |
|||||||
/*
|
|
||||||
* |
|
||||||
* Copyright 2015 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 <grpcpp/support/status.h> |
|
||||||
|
|
||||||
#include <grpc/status.h> |
|
||||||
#include <grpc/support/log.h> |
|
||||||
|
|
||||||
// Make sure the existing grpc_status_code match with grpc::Code.
|
|
||||||
int main(int argc, char** argv) { |
|
||||||
GPR_ASSERT(grpc::StatusCode::OK == |
|
||||||
static_cast<grpc::StatusCode>(GRPC_STATUS_OK)); |
|
||||||
GPR_ASSERT(grpc::StatusCode::CANCELLED == |
|
||||||
static_cast<grpc::StatusCode>(GRPC_STATUS_CANCELLED)); |
|
||||||
GPR_ASSERT(grpc::StatusCode::UNKNOWN == |
|
||||||
static_cast<grpc::StatusCode>(GRPC_STATUS_UNKNOWN)); |
|
||||||
GPR_ASSERT(grpc::StatusCode::INVALID_ARGUMENT == |
|
||||||
static_cast<grpc::StatusCode>(GRPC_STATUS_INVALID_ARGUMENT)); |
|
||||||
GPR_ASSERT(grpc::StatusCode::DEADLINE_EXCEEDED == |
|
||||||
static_cast<grpc::StatusCode>(GRPC_STATUS_DEADLINE_EXCEEDED)); |
|
||||||
GPR_ASSERT(grpc::StatusCode::NOT_FOUND == |
|
||||||
static_cast<grpc::StatusCode>(GRPC_STATUS_NOT_FOUND)); |
|
||||||
GPR_ASSERT(grpc::StatusCode::ALREADY_EXISTS == |
|
||||||
static_cast<grpc::StatusCode>(GRPC_STATUS_ALREADY_EXISTS)); |
|
||||||
GPR_ASSERT(grpc::StatusCode::PERMISSION_DENIED == |
|
||||||
static_cast<grpc::StatusCode>(GRPC_STATUS_PERMISSION_DENIED)); |
|
||||||
GPR_ASSERT(grpc::StatusCode::UNAUTHENTICATED == |
|
||||||
static_cast<grpc::StatusCode>(GRPC_STATUS_UNAUTHENTICATED)); |
|
||||||
GPR_ASSERT(grpc::StatusCode::RESOURCE_EXHAUSTED == |
|
||||||
static_cast<grpc::StatusCode>(GRPC_STATUS_RESOURCE_EXHAUSTED)); |
|
||||||
GPR_ASSERT(grpc::StatusCode::FAILED_PRECONDITION == |
|
||||||
static_cast<grpc::StatusCode>(GRPC_STATUS_FAILED_PRECONDITION)); |
|
||||||
GPR_ASSERT(grpc::StatusCode::ABORTED == |
|
||||||
static_cast<grpc::StatusCode>(GRPC_STATUS_ABORTED)); |
|
||||||
GPR_ASSERT(grpc::StatusCode::OUT_OF_RANGE == |
|
||||||
static_cast<grpc::StatusCode>(GRPC_STATUS_OUT_OF_RANGE)); |
|
||||||
GPR_ASSERT(grpc::StatusCode::UNIMPLEMENTED == |
|
||||||
static_cast<grpc::StatusCode>(GRPC_STATUS_UNIMPLEMENTED)); |
|
||||||
GPR_ASSERT(grpc::StatusCode::INTERNAL == |
|
||||||
static_cast<grpc::StatusCode>(GRPC_STATUS_INTERNAL)); |
|
||||||
GPR_ASSERT(grpc::StatusCode::UNAVAILABLE == |
|
||||||
static_cast<grpc::StatusCode>(GRPC_STATUS_UNAVAILABLE)); |
|
||||||
GPR_ASSERT(grpc::StatusCode::DATA_LOSS == |
|
||||||
static_cast<grpc::StatusCode>(GRPC_STATUS_DATA_LOSS)); |
|
||||||
|
|
||||||
return 0; |
|
||||||
} |
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue