mirror of https://github.com/grpc/grpc.git
Merge branch 'master' of https://github.com/grpc/grpc into channelz
commit
68d4f50f77
176 changed files with 4577 additions and 1811 deletions
@ -0,0 +1,41 @@ |
||||
/*
|
||||
* |
||||
* 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 GRPCPP_OPENCENSUS_H |
||||
#define GRPCPP_OPENCENSUS_H |
||||
|
||||
namespace grpc { |
||||
// These symbols in this file will not be included in the binary unless
|
||||
// grpc_opencensus_plugin build target was added as a dependency. At the moment
|
||||
// it is only setup to be built with Bazel.
|
||||
|
||||
// Registers the OpenCensus plugin with gRPC, so that it will be used for future
|
||||
// RPCs. This must be called before any views are created.
|
||||
void RegisterOpenCensusPlugin(); |
||||
|
||||
// RPC stats definitions, defined by
|
||||
// https://github.com/census-instrumentation/opencensus-specs/blob/master/stats/gRPC.md
|
||||
|
||||
// Registers the cumulative gRPC views so that they will be exported by any
|
||||
// registered stats exporter. For on-task stats, construct a View using the
|
||||
// ViewDescriptors below.
|
||||
void RegisterOpenCensusViewsForExport(); |
||||
|
||||
} // namespace grpc
|
||||
|
||||
#endif // GRPCPP_OPENCENSUS_H
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,311 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016 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/support/port_platform.h> |
||||
|
||||
#include "src/core/lib/iomgr/port.h" |
||||
#if GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) |
||||
|
||||
#include <ares.h> |
||||
#include <string.h> |
||||
#include <sys/ioctl.h> |
||||
|
||||
#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h" |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/log.h> |
||||
#include <grpc/support/string_util.h> |
||||
#include <grpc/support/time.h> |
||||
#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" |
||||
#include "src/core/lib/gpr/string.h" |
||||
#include "src/core/lib/iomgr/ev_posix.h" |
||||
#include "src/core/lib/iomgr/iomgr_internal.h" |
||||
#include "src/core/lib/iomgr/sockaddr_utils.h" |
||||
|
||||
typedef struct fd_node { |
||||
/** the owner of this fd node */ |
||||
grpc_ares_ev_driver* ev_driver; |
||||
/** a closure wrapping on_readable_locked, which should be
|
||||
invoked when the grpc_fd in this node becomes readable. */ |
||||
grpc_closure read_closure; |
||||
/** a closure wrapping on_writable_locked, which should be
|
||||
invoked when the grpc_fd in this node becomes writable. */ |
||||
grpc_closure write_closure; |
||||
/** next fd node in the list */ |
||||
struct fd_node* next; |
||||
|
||||
/** wrapped fd that's polled by grpc's poller for the current platform */ |
||||
grpc_core::GrpcPolledFd* grpc_polled_fd; |
||||
/** if the readable closure has been registered */ |
||||
bool readable_registered; |
||||
/** if the writable closure has been registered */ |
||||
bool writable_registered; |
||||
/** if the fd has been shutdown yet from grpc iomgr perspective */ |
||||
bool already_shutdown; |
||||
} fd_node; |
||||
|
||||
struct grpc_ares_ev_driver { |
||||
/** the ares_channel owned by this event driver */ |
||||
ares_channel channel; |
||||
/** pollset set for driving the IO events of the channel */ |
||||
grpc_pollset_set* pollset_set; |
||||
/** refcount of the event driver */ |
||||
gpr_refcount refs; |
||||
|
||||
/** combiner to synchronize c-ares and I/O callbacks on */ |
||||
grpc_combiner* combiner; |
||||
/** a list of grpc_fd that this event driver is currently using. */ |
||||
fd_node* fds; |
||||
/** is this event driver currently working? */ |
||||
bool working; |
||||
/** is this event driver being shut down */ |
||||
bool shutting_down; |
||||
}; |
||||
|
||||
static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver); |
||||
|
||||
static grpc_ares_ev_driver* grpc_ares_ev_driver_ref( |
||||
grpc_ares_ev_driver* ev_driver) { |
||||
gpr_log(GPR_DEBUG, "Ref ev_driver %" PRIuPTR, (uintptr_t)ev_driver); |
||||
gpr_ref(&ev_driver->refs); |
||||
return ev_driver; |
||||
} |
||||
|
||||
static void grpc_ares_ev_driver_unref(grpc_ares_ev_driver* ev_driver) { |
||||
gpr_log(GPR_DEBUG, "Unref ev_driver %" PRIuPTR, (uintptr_t)ev_driver); |
||||
if (gpr_unref(&ev_driver->refs)) { |
||||
gpr_log(GPR_DEBUG, "destroy ev_driver %" PRIuPTR, (uintptr_t)ev_driver); |
||||
GPR_ASSERT(ev_driver->fds == nullptr); |
||||
GRPC_COMBINER_UNREF(ev_driver->combiner, "free ares event driver"); |
||||
ares_destroy(ev_driver->channel); |
||||
gpr_free(ev_driver); |
||||
} |
||||
} |
||||
|
||||
static void fd_node_destroy_locked(fd_node* fdn) { |
||||
gpr_log(GPR_DEBUG, "delete fd: %s", fdn->grpc_polled_fd->GetName()); |
||||
GPR_ASSERT(!fdn->readable_registered); |
||||
GPR_ASSERT(!fdn->writable_registered); |
||||
GPR_ASSERT(fdn->already_shutdown); |
||||
grpc_core::Delete(fdn->grpc_polled_fd); |
||||
gpr_free(fdn); |
||||
} |
||||
|
||||
static void fd_node_shutdown_locked(fd_node* fdn, const char* reason) { |
||||
if (!fdn->already_shutdown) { |
||||
fdn->already_shutdown = true; |
||||
fdn->grpc_polled_fd->ShutdownLocked( |
||||
GRPC_ERROR_CREATE_FROM_STATIC_STRING(reason)); |
||||
} |
||||
} |
||||
|
||||
grpc_error* grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver** ev_driver, |
||||
grpc_pollset_set* pollset_set, |
||||
grpc_combiner* combiner) { |
||||
*ev_driver = static_cast<grpc_ares_ev_driver*>( |
||||
gpr_malloc(sizeof(grpc_ares_ev_driver))); |
||||
ares_options opts; |
||||
memset(&opts, 0, sizeof(opts)); |
||||
opts.flags |= ARES_FLAG_STAYOPEN; |
||||
int status = ares_init_options(&(*ev_driver)->channel, &opts, ARES_OPT_FLAGS); |
||||
grpc_core::ConfigureAresChannelLocked(&(*ev_driver)->channel); |
||||
gpr_log(GPR_DEBUG, "grpc_ares_ev_driver_create_locked"); |
||||
if (status != ARES_SUCCESS) { |
||||
char* err_msg; |
||||
gpr_asprintf(&err_msg, "Failed to init ares channel. C-ares error: %s", |
||||
ares_strerror(status)); |
||||
grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(err_msg); |
||||
gpr_free(err_msg); |
||||
gpr_free(*ev_driver); |
||||
return err; |
||||
} |
||||
(*ev_driver)->combiner = GRPC_COMBINER_REF(combiner, "ares event driver"); |
||||
gpr_ref_init(&(*ev_driver)->refs, 1); |
||||
(*ev_driver)->pollset_set = pollset_set; |
||||
(*ev_driver)->fds = nullptr; |
||||
(*ev_driver)->working = false; |
||||
(*ev_driver)->shutting_down = false; |
||||
return GRPC_ERROR_NONE; |
||||
} |
||||
|
||||
void grpc_ares_ev_driver_destroy_locked(grpc_ares_ev_driver* ev_driver) { |
||||
// We mark the event driver as being shut down. If the event driver
|
||||
// is working, grpc_ares_notify_on_event_locked will shut down the
|
||||
// fds; if it's not working, there are no fds to shut down.
|
||||
ev_driver->shutting_down = true; |
||||
grpc_ares_ev_driver_unref(ev_driver); |
||||
} |
||||
|
||||
void grpc_ares_ev_driver_shutdown_locked(grpc_ares_ev_driver* ev_driver) { |
||||
ev_driver->shutting_down = true; |
||||
fd_node* fn = ev_driver->fds; |
||||
while (fn != nullptr) { |
||||
fd_node_shutdown_locked(fn, "grpc_ares_ev_driver_shutdown"); |
||||
fn = fn->next; |
||||
} |
||||
} |
||||
|
||||
// Search fd in the fd_node list head. This is an O(n) search, the max possible
|
||||
// value of n is ARES_GETSOCK_MAXNUM (16). n is typically 1 - 2 in our tests.
|
||||
static fd_node* pop_fd_node_locked(fd_node** head, ares_socket_t as) { |
||||
fd_node dummy_head; |
||||
dummy_head.next = *head; |
||||
fd_node* node = &dummy_head; |
||||
while (node->next != nullptr) { |
||||
if (node->next->grpc_polled_fd->GetWrappedAresSocketLocked() == as) { |
||||
fd_node* ret = node->next; |
||||
node->next = node->next->next; |
||||
*head = dummy_head.next; |
||||
return ret; |
||||
} |
||||
node = node->next; |
||||
} |
||||
return nullptr; |
||||
} |
||||
|
||||
static void on_readable_locked(void* arg, grpc_error* error) { |
||||
fd_node* fdn = static_cast<fd_node*>(arg); |
||||
grpc_ares_ev_driver* ev_driver = fdn->ev_driver; |
||||
const ares_socket_t as = fdn->grpc_polled_fd->GetWrappedAresSocketLocked(); |
||||
fdn->readable_registered = false; |
||||
gpr_log(GPR_DEBUG, "readable on %s", fdn->grpc_polled_fd->GetName()); |
||||
if (error == GRPC_ERROR_NONE) { |
||||
do { |
||||
ares_process_fd(ev_driver->channel, as, ARES_SOCKET_BAD); |
||||
} while (fdn->grpc_polled_fd->IsFdStillReadableLocked()); |
||||
} else { |
||||
// If error is not GRPC_ERROR_NONE, it means the fd has been shutdown or
|
||||
// timed out. The pending lookups made on this ev_driver will be cancelled
|
||||
// by the following ares_cancel() and the on_done callbacks will be invoked
|
||||
// with a status of ARES_ECANCELLED. The remaining file descriptors in this
|
||||
// ev_driver will be cleaned up in the follwing
|
||||
// grpc_ares_notify_on_event_locked().
|
||||
ares_cancel(ev_driver->channel); |
||||
} |
||||
grpc_ares_notify_on_event_locked(ev_driver); |
||||
grpc_ares_ev_driver_unref(ev_driver); |
||||
} |
||||
|
||||
static void on_writable_locked(void* arg, grpc_error* error) { |
||||
fd_node* fdn = static_cast<fd_node*>(arg); |
||||
grpc_ares_ev_driver* ev_driver = fdn->ev_driver; |
||||
const ares_socket_t as = fdn->grpc_polled_fd->GetWrappedAresSocketLocked(); |
||||
fdn->writable_registered = false; |
||||
gpr_log(GPR_DEBUG, "writable on %s", fdn->grpc_polled_fd->GetName()); |
||||
if (error == GRPC_ERROR_NONE) { |
||||
ares_process_fd(ev_driver->channel, ARES_SOCKET_BAD, as); |
||||
} else { |
||||
// If error is not GRPC_ERROR_NONE, it means the fd has been shutdown or
|
||||
// timed out. The pending lookups made on this ev_driver will be cancelled
|
||||
// by the following ares_cancel() and the on_done callbacks will be invoked
|
||||
// with a status of ARES_ECANCELLED. The remaining file descriptors in this
|
||||
// ev_driver will be cleaned up in the follwing
|
||||
// grpc_ares_notify_on_event_locked().
|
||||
ares_cancel(ev_driver->channel); |
||||
} |
||||
grpc_ares_notify_on_event_locked(ev_driver); |
||||
grpc_ares_ev_driver_unref(ev_driver); |
||||
} |
||||
|
||||
ares_channel* grpc_ares_ev_driver_get_channel_locked( |
||||
grpc_ares_ev_driver* ev_driver) { |
||||
return &ev_driver->channel; |
||||
} |
||||
|
||||
// Get the file descriptors used by the ev_driver's ares channel, register
|
||||
// driver_closure with these filedescriptors.
|
||||
static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver) { |
||||
fd_node* new_list = nullptr; |
||||
if (!ev_driver->shutting_down) { |
||||
ares_socket_t socks[ARES_GETSOCK_MAXNUM]; |
||||
int socks_bitmask = |
||||
ares_getsock(ev_driver->channel, socks, ARES_GETSOCK_MAXNUM); |
||||
for (size_t i = 0; i < ARES_GETSOCK_MAXNUM; i++) { |
||||
if (ARES_GETSOCK_READABLE(socks_bitmask, i) || |
||||
ARES_GETSOCK_WRITABLE(socks_bitmask, i)) { |
||||
fd_node* fdn = pop_fd_node_locked(&ev_driver->fds, socks[i]); |
||||
// Create a new fd_node if sock[i] is not in the fd_node list.
|
||||
if (fdn == nullptr) { |
||||
fdn = static_cast<fd_node*>(gpr_malloc(sizeof(fd_node))); |
||||
fdn->grpc_polled_fd = grpc_core::NewGrpcPolledFdLocked( |
||||
socks[i], ev_driver->pollset_set); |
||||
gpr_log(GPR_DEBUG, "new fd: %s", fdn->grpc_polled_fd->GetName()); |
||||
fdn->ev_driver = ev_driver; |
||||
fdn->readable_registered = false; |
||||
fdn->writable_registered = false; |
||||
fdn->already_shutdown = false; |
||||
GRPC_CLOSURE_INIT(&fdn->read_closure, on_readable_locked, fdn, |
||||
grpc_combiner_scheduler(ev_driver->combiner)); |
||||
GRPC_CLOSURE_INIT(&fdn->write_closure, on_writable_locked, fdn, |
||||
grpc_combiner_scheduler(ev_driver->combiner)); |
||||
} |
||||
fdn->next = new_list; |
||||
new_list = fdn; |
||||
// Register read_closure if the socket is readable and read_closure has
|
||||
// not been registered with this socket.
|
||||
if (ARES_GETSOCK_READABLE(socks_bitmask, i) && |
||||
!fdn->readable_registered) { |
||||
grpc_ares_ev_driver_ref(ev_driver); |
||||
gpr_log(GPR_DEBUG, "notify read on: %s", |
||||
fdn->grpc_polled_fd->GetName()); |
||||
fdn->grpc_polled_fd->RegisterForOnReadableLocked(&fdn->read_closure); |
||||
fdn->readable_registered = true; |
||||
} |
||||
// Register write_closure if the socket is writable and write_closure
|
||||
// has not been registered with this socket.
|
||||
if (ARES_GETSOCK_WRITABLE(socks_bitmask, i) && |
||||
!fdn->writable_registered) { |
||||
gpr_log(GPR_DEBUG, "notify write on: %s", |
||||
fdn->grpc_polled_fd->GetName()); |
||||
grpc_ares_ev_driver_ref(ev_driver); |
||||
fdn->grpc_polled_fd->RegisterForOnWriteableLocked( |
||||
&fdn->write_closure); |
||||
fdn->writable_registered = true; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
// Any remaining fds in ev_driver->fds were not returned by ares_getsock() and
|
||||
// are therefore no longer in use, so they can be shut down and removed from
|
||||
// the list.
|
||||
while (ev_driver->fds != nullptr) { |
||||
fd_node* cur = ev_driver->fds; |
||||
ev_driver->fds = ev_driver->fds->next; |
||||
fd_node_shutdown_locked(cur, "c-ares fd shutdown"); |
||||
if (!cur->readable_registered && !cur->writable_registered) { |
||||
fd_node_destroy_locked(cur); |
||||
} else { |
||||
cur->next = new_list; |
||||
new_list = cur; |
||||
} |
||||
} |
||||
ev_driver->fds = new_list; |
||||
// If the ev driver has no working fd, all the tasks are done.
|
||||
if (new_list == nullptr) { |
||||
ev_driver->working = false; |
||||
gpr_log(GPR_DEBUG, "ev driver stop working"); |
||||
} |
||||
} |
||||
|
||||
void grpc_ares_ev_driver_start_locked(grpc_ares_ev_driver* ev_driver) { |
||||
if (!ev_driver->working) { |
||||
ev_driver->working = true; |
||||
grpc_ares_notify_on_event_locked(ev_driver); |
||||
} |
||||
} |
||||
|
||||
#endif /* GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) */ |
@ -0,0 +1,163 @@ |
||||
/*
|
||||
* |
||||
* 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 <grpc/support/port_platform.h> |
||||
|
||||
#include "src/cpp/ext/filters/census/client_filter.h" |
||||
|
||||
#include "absl/strings/str_cat.h" |
||||
#include "absl/strings/string_view.h" |
||||
#include "opencensus/stats/stats.h" |
||||
#include "src/core/lib/surface/call.h" |
||||
#include "src/cpp/ext/filters/census/grpc_plugin.h" |
||||
#include "src/cpp/ext/filters/census/measures.h" |
||||
|
||||
namespace grpc { |
||||
|
||||
constexpr uint32_t CensusClientCallData::kMaxTraceContextLen; |
||||
constexpr uint32_t CensusClientCallData::kMaxTagsLen; |
||||
|
||||
namespace { |
||||
|
||||
void FilterTrailingMetadata(grpc_metadata_batch* b, uint64_t* elapsed_time) { |
||||
if (b->idx.named.grpc_server_stats_bin != nullptr) { |
||||
ServerStatsDeserialize( |
||||
reinterpret_cast<const char*>(GRPC_SLICE_START_PTR( |
||||
GRPC_MDVALUE(b->idx.named.grpc_server_stats_bin->md))), |
||||
GRPC_SLICE_LENGTH(GRPC_MDVALUE(b->idx.named.grpc_server_stats_bin->md)), |
||||
elapsed_time); |
||||
grpc_metadata_batch_remove(b, b->idx.named.grpc_server_stats_bin); |
||||
} |
||||
} |
||||
|
||||
} // namespace
|
||||
|
||||
void CensusClientCallData::OnDoneRecvTrailingMetadataCb(void* user_data, |
||||
grpc_error* error) { |
||||
grpc_call_element* elem = reinterpret_cast<grpc_call_element*>(user_data); |
||||
CensusClientCallData* calld = |
||||
reinterpret_cast<CensusClientCallData*>(elem->call_data); |
||||
GPR_ASSERT(calld != nullptr); |
||||
if (error == GRPC_ERROR_NONE) { |
||||
GPR_ASSERT(calld->recv_trailing_metadata_ != nullptr); |
||||
FilterTrailingMetadata(calld->recv_trailing_metadata_, |
||||
&calld->elapsed_time_); |
||||
} |
||||
GRPC_CLOSURE_RUN(calld->initial_on_done_recv_trailing_metadata_, |
||||
GRPC_ERROR_REF(error)); |
||||
} |
||||
|
||||
void CensusClientCallData::OnDoneRecvMessageCb(void* user_data, |
||||
grpc_error* error) { |
||||
grpc_call_element* elem = reinterpret_cast<grpc_call_element*>(user_data); |
||||
CensusClientCallData* calld = |
||||
reinterpret_cast<CensusClientCallData*>(elem->call_data); |
||||
CensusChannelData* channeld = |
||||
reinterpret_cast<CensusChannelData*>(elem->channel_data); |
||||
GPR_ASSERT(calld != nullptr); |
||||
GPR_ASSERT(channeld != nullptr); |
||||
// Stream messages are no longer valid after receiving trailing metadata.
|
||||
if ((*calld->recv_message_) != nullptr) { |
||||
calld->recv_message_count_++; |
||||
} |
||||
GRPC_CLOSURE_RUN(calld->initial_on_done_recv_message_, GRPC_ERROR_REF(error)); |
||||
} |
||||
|
||||
void CensusClientCallData::StartTransportStreamOpBatch( |
||||
grpc_call_element* elem, TransportStreamOpBatch* op) { |
||||
if (op->send_initial_metadata() != nullptr) { |
||||
census_context* ctxt = op->get_census_context(); |
||||
GenerateClientContext( |
||||
qualified_method_, &context_, |
||||
(ctxt == nullptr) ? nullptr : reinterpret_cast<CensusContext*>(ctxt)); |
||||
size_t tracing_len = TraceContextSerialize(context_.Context(), tracing_buf_, |
||||
kMaxTraceContextLen); |
||||
if (tracing_len > 0) { |
||||
GRPC_LOG_IF_ERROR( |
||||
"census grpc_filter", |
||||
grpc_metadata_batch_add_tail( |
||||
op->send_initial_metadata()->batch(), &tracing_bin_, |
||||
grpc_mdelem_from_slices( |
||||
GRPC_MDSTR_GRPC_TRACE_BIN, |
||||
grpc_slice_from_copied_buffer(tracing_buf_, tracing_len)))); |
||||
} |
||||
grpc_slice tags = grpc_empty_slice(); |
||||
// TODO: Add in tagging serialization.
|
||||
size_t encoded_tags_len = StatsContextSerialize(kMaxTagsLen, &tags); |
||||
if (encoded_tags_len > 0) { |
||||
GRPC_LOG_IF_ERROR( |
||||
"census grpc_filter", |
||||
grpc_metadata_batch_add_tail( |
||||
op->send_initial_metadata()->batch(), &stats_bin_, |
||||
grpc_mdelem_from_slices(GRPC_MDSTR_GRPC_TAGS_BIN, tags))); |
||||
} |
||||
} |
||||
|
||||
if (op->send_message() != nullptr) { |
||||
++sent_message_count_; |
||||
} |
||||
if (op->recv_message() != nullptr) { |
||||
recv_message_ = op->op()->payload->recv_message.recv_message; |
||||
initial_on_done_recv_message_ = |
||||
op->op()->payload->recv_message.recv_message_ready; |
||||
op->op()->payload->recv_message.recv_message_ready = &on_done_recv_message_; |
||||
} |
||||
if (op->recv_trailing_metadata() != nullptr) { |
||||
recv_trailing_metadata_ = op->recv_trailing_metadata()->batch(); |
||||
initial_on_done_recv_trailing_metadata_ = op->on_complete(); |
||||
op->set_on_complete(&on_done_recv_trailing_metadata_); |
||||
} |
||||
// Call next op.
|
||||
grpc_call_next_op(elem, op->op()); |
||||
} |
||||
|
||||
grpc_error* CensusClientCallData::Init(grpc_call_element* elem, |
||||
const grpc_call_element_args* args) { |
||||
path_ = grpc_slice_ref_internal(args->path); |
||||
start_time_ = absl::Now(); |
||||
method_ = GetMethod(&path_); |
||||
qualified_method_ = absl::StrCat("Sent.", method_); |
||||
GRPC_CLOSURE_INIT(&on_done_recv_message_, OnDoneRecvMessageCb, elem, |
||||
grpc_schedule_on_exec_ctx); |
||||
GRPC_CLOSURE_INIT(&on_done_recv_trailing_metadata_, |
||||
OnDoneRecvTrailingMetadataCb, elem, |
||||
grpc_schedule_on_exec_ctx); |
||||
return GRPC_ERROR_NONE; |
||||
} |
||||
|
||||
void CensusClientCallData::Destroy(grpc_call_element* elem, |
||||
const grpc_call_final_info* final_info, |
||||
grpc_closure* then_call_closure) { |
||||
const uint64_t request_size = GetOutgoingDataSize(final_info); |
||||
const uint64_t response_size = GetIncomingDataSize(final_info); |
||||
double latency_ms = absl::ToDoubleMilliseconds(absl::Now() - start_time_); |
||||
::opencensus::stats::Record( |
||||
{{RpcClientSentBytesPerRpc(), static_cast<double>(request_size)}, |
||||
{RpcClientReceivedBytesPerRpc(), static_cast<double>(response_size)}, |
||||
{RpcClientRoundtripLatency(), latency_ms}, |
||||
{RpcClientServerLatency(), |
||||
ToDoubleMilliseconds(absl::Nanoseconds(elapsed_time_))}, |
||||
{RpcClientSentMessagesPerRpc(), sent_message_count_}, |
||||
{RpcClientReceivedMessagesPerRpc(), recv_message_count_}}, |
||||
{{ClientMethodTagKey(), method_}, |
||||
{ClientStatusTagKey(), StatusCodeToString(final_info->final_status)}}); |
||||
grpc_slice_unref_internal(path_); |
||||
context_.EndSpan(); |
||||
} |
||||
|
||||
} // namespace grpc
|
@ -0,0 +1,104 @@ |
||||
/*
|
||||
* |
||||
* 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_INTERNAL_CPP_EXT_FILTERS_CENSUS_CLIENT_FILTER_H |
||||
#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CLIENT_FILTER_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "absl/strings/string_view.h" |
||||
#include "absl/time/time.h" |
||||
#include "src/cpp/ext/filters/census/channel_filter.h" |
||||
#include "src/cpp/ext/filters/census/context.h" |
||||
|
||||
namespace grpc { |
||||
|
||||
// A CallData class will be created for every grpc call within a channel. It is
|
||||
// used to store data and methods specific to that call. CensusClientCallData is
|
||||
// thread-compatible, however typically only 1 thread should be interacting with
|
||||
// a call at a time.
|
||||
class CensusClientCallData : public CallData { |
||||
public: |
||||
// Maximum size of trace context is sent on the wire.
|
||||
static constexpr uint32_t kMaxTraceContextLen = 64; |
||||
// Maximum size of tags that are sent on the wire.
|
||||
static constexpr uint32_t kMaxTagsLen = 2048; |
||||
|
||||
CensusClientCallData() |
||||
: recv_trailing_metadata_(nullptr), |
||||
initial_on_done_recv_trailing_metadata_(nullptr), |
||||
initial_on_done_recv_message_(nullptr), |
||||
elapsed_time_(0), |
||||
recv_message_(nullptr), |
||||
recv_message_count_(0), |
||||
sent_message_count_(0) { |
||||
memset(&stats_bin_, 0, sizeof(grpc_linked_mdelem)); |
||||
memset(&tracing_bin_, 0, sizeof(grpc_linked_mdelem)); |
||||
memset(&path_, 0, sizeof(grpc_slice)); |
||||
memset(&on_done_recv_trailing_metadata_, 0, sizeof(grpc_closure)); |
||||
memset(&on_done_recv_message_, 0, sizeof(grpc_closure)); |
||||
} |
||||
|
||||
grpc_error* Init(grpc_call_element* elem, |
||||
const grpc_call_element_args* args) override; |
||||
|
||||
void Destroy(grpc_call_element* elem, const grpc_call_final_info* final_info, |
||||
grpc_closure* then_call_closure) override; |
||||
|
||||
void StartTransportStreamOpBatch(grpc_call_element* elem, |
||||
TransportStreamOpBatch* op) override; |
||||
|
||||
static void OnDoneRecvTrailingMetadataCb(void* user_data, grpc_error* error); |
||||
|
||||
static void OnDoneSendInitialMetadataCb(void* user_data, grpc_error* error); |
||||
|
||||
static void OnDoneRecvMessageCb(void* user_data, grpc_error* error); |
||||
|
||||
private: |
||||
CensusContext context_; |
||||
// Metadata elements for tracing and census stats data.
|
||||
grpc_linked_mdelem stats_bin_; |
||||
grpc_linked_mdelem tracing_bin_; |
||||
// Client method.
|
||||
absl::string_view method_; |
||||
std::string qualified_method_; |
||||
grpc_slice path_; |
||||
// The recv trailing metadata callbacks.
|
||||
grpc_metadata_batch* recv_trailing_metadata_; |
||||
grpc_closure* initial_on_done_recv_trailing_metadata_; |
||||
grpc_closure on_done_recv_trailing_metadata_; |
||||
// recv message
|
||||
grpc_closure* initial_on_done_recv_message_; |
||||
grpc_closure on_done_recv_message_; |
||||
// Start time (for measuring latency).
|
||||
absl::Time start_time_; |
||||
// Server elapsed time in nanoseconds.
|
||||
uint64_t elapsed_time_; |
||||
// The received message--may be null.
|
||||
grpc_core::OrphanablePtr<grpc_core::ByteStream>* recv_message_; |
||||
// Number of messages in this RPC.
|
||||
uint64_t recv_message_count_; |
||||
uint64_t sent_message_count_; |
||||
// Buffer needed for grpc_slice to reference when adding trace context
|
||||
// metatdata to outgoing message.
|
||||
char tracing_buf_[kMaxTraceContextLen]; |
||||
}; |
||||
|
||||
} // namespace grpc
|
||||
|
||||
#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CLIENT_FILTER_H */ |
@ -0,0 +1,132 @@ |
||||
/*
|
||||
* |
||||
* 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 <grpc/support/port_platform.h> |
||||
|
||||
#include "src/cpp/ext/filters/census/context.h" |
||||
|
||||
namespace grpc { |
||||
|
||||
using ::opencensus::trace::Span; |
||||
using ::opencensus::trace::SpanContext; |
||||
|
||||
void GenerateServerContext(absl::string_view tracing, absl::string_view stats, |
||||
absl::string_view primary_role, |
||||
absl::string_view method, CensusContext* context) { |
||||
GrpcTraceContext trace_ctxt; |
||||
TraceContextEncoding::Decode(tracing, &trace_ctxt); |
||||
SpanContext parent_ctx = trace_ctxt.ToSpanContext(); |
||||
new (context) CensusContext(method, parent_ctx); |
||||
} |
||||
|
||||
void GenerateClientContext(absl::string_view method, CensusContext* ctxt, |
||||
CensusContext* parent_ctxt) { |
||||
if (parent_ctxt != nullptr) { |
||||
SpanContext span_ctxt = parent_ctxt->Context(); |
||||
Span span = parent_ctxt->Span(); |
||||
if (span_ctxt.IsValid()) { |
||||
new (ctxt) CensusContext(method, &span); |
||||
return; |
||||
} |
||||
} |
||||
new (ctxt) CensusContext(method); |
||||
} |
||||
|
||||
size_t TraceContextSerialize(const ::opencensus::trace::SpanContext& context, |
||||
char* tracing_buf, size_t tracing_buf_size) { |
||||
GrpcTraceContext trace_ctxt(context); |
||||
return TraceContextEncoding::Encode(trace_ctxt, tracing_buf, |
||||
tracing_buf_size); |
||||
} |
||||
|
||||
size_t StatsContextSerialize(size_t max_tags_len, grpc_slice* tags) { |
||||
// TODO: Add implementation. Waiting on stats tagging to be added.
|
||||
return 0; |
||||
} |
||||
|
||||
size_t ServerStatsSerialize(uint64_t server_elapsed_time, char* buf, |
||||
size_t buf_size) { |
||||
return RpcServerStatsEncoding::Encode(server_elapsed_time, buf, buf_size); |
||||
} |
||||
|
||||
size_t ServerStatsDeserialize(const char* buf, size_t buf_size, |
||||
uint64_t* server_elapsed_time) { |
||||
return RpcServerStatsEncoding::Decode(absl::string_view(buf, buf_size), |
||||
server_elapsed_time); |
||||
} |
||||
|
||||
uint64_t GetIncomingDataSize(const grpc_call_final_info* final_info) { |
||||
return final_info->stats.transport_stream_stats.incoming.data_bytes; |
||||
} |
||||
|
||||
uint64_t GetOutgoingDataSize(const grpc_call_final_info* final_info) { |
||||
return final_info->stats.transport_stream_stats.outgoing.data_bytes; |
||||
} |
||||
|
||||
SpanContext SpanContextFromCensusContext(const census_context* ctxt) { |
||||
return reinterpret_cast<const CensusContext*>(ctxt)->Context(); |
||||
} |
||||
|
||||
Span SpanFromCensusContext(const census_context* ctxt) { |
||||
return reinterpret_cast<const CensusContext*>(ctxt)->Span(); |
||||
} |
||||
|
||||
absl::string_view StatusCodeToString(grpc_status_code code) { |
||||
switch (code) { |
||||
case GRPC_STATUS_OK: |
||||
return "OK"; |
||||
case GRPC_STATUS_CANCELLED: |
||||
return "CANCELLED"; |
||||
case GRPC_STATUS_UNKNOWN: |
||||
return "UNKNOWN"; |
||||
case GRPC_STATUS_INVALID_ARGUMENT: |
||||
return "INVALID_ARGUMENT"; |
||||
case GRPC_STATUS_DEADLINE_EXCEEDED: |
||||
return "DEADLINE_EXCEEDED"; |
||||
case GRPC_STATUS_NOT_FOUND: |
||||
return "NOT_FOUND"; |
||||
case GRPC_STATUS_ALREADY_EXISTS: |
||||
return "ALREADY_EXISTS"; |
||||
case GRPC_STATUS_PERMISSION_DENIED: |
||||
return "PERMISSION_DENIED"; |
||||
case GRPC_STATUS_UNAUTHENTICATED: |
||||
return "UNAUTHENTICATED"; |
||||
case GRPC_STATUS_RESOURCE_EXHAUSTED: |
||||
return "RESOURCE_EXHAUSTED"; |
||||
case GRPC_STATUS_FAILED_PRECONDITION: |
||||
return "FAILED_PRECONDITION"; |
||||
case GRPC_STATUS_ABORTED: |
||||
return "ABORTED"; |
||||
case GRPC_STATUS_OUT_OF_RANGE: |
||||
return "OUT_OF_RANGE"; |
||||
case GRPC_STATUS_UNIMPLEMENTED: |
||||
return "UNIMPLEMENTED"; |
||||
case GRPC_STATUS_INTERNAL: |
||||
return "INTERNAL"; |
||||
case GRPC_STATUS_UNAVAILABLE: |
||||
return "UNAVAILABLE"; |
||||
case GRPC_STATUS_DATA_LOSS: |
||||
return "DATA_LOSS"; |
||||
default: |
||||
// gRPC wants users of this enum to include a default branch so that
|
||||
// adding values is not a breaking change.
|
||||
return "UNKNOWN_STATUS"; |
||||
} |
||||
} |
||||
|
||||
} // namespace grpc
|
@ -0,0 +1,126 @@ |
||||
/*
|
||||
* |
||||
* 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_INTERNAL_CPP_EXT_FILTERS_CENSUS_CONTEXT_H |
||||
#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CONTEXT_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include <grpc/status.h> |
||||
#include "absl/memory/memory.h" |
||||
#include "absl/strings/string_view.h" |
||||
#include "absl/strings/strip.h" |
||||
#include "opencensus/trace/span.h" |
||||
#include "opencensus/trace/span_context.h" |
||||
#include "opencensus/trace/trace_params.h" |
||||
#include "src/core/lib/slice/slice_internal.h" |
||||
#include "src/cpp/common/channel_filter.h" |
||||
#include "src/cpp/ext/filters/census/rpc_encoding.h" |
||||
|
||||
// This is needed because grpc has hardcoded CensusContext with a
|
||||
// forward declaration of 'struct census_context;'
|
||||
struct census_context; |
||||
|
||||
namespace grpc { |
||||
|
||||
// Thread compatible.
|
||||
class CensusContext { |
||||
public: |
||||
CensusContext() : span_(::opencensus::trace::Span::BlankSpan()) {} |
||||
|
||||
explicit CensusContext(absl::string_view name) |
||||
: span_(::opencensus::trace::Span::StartSpan(name)) {} |
||||
|
||||
CensusContext(absl::string_view name, const ::opencensus::trace::Span* parent) |
||||
: span_(::opencensus::trace::Span::StartSpan(name, parent)) {} |
||||
|
||||
CensusContext(absl::string_view name, |
||||
const ::opencensus::trace::SpanContext& parent_ctxt) |
||||
: span_(::opencensus::trace::Span::StartSpanWithRemoteParent( |
||||
name, parent_ctxt)) {} |
||||
|
||||
::opencensus::trace::SpanContext Context() const { return span_.context(); } |
||||
::opencensus::trace::Span Span() const { return span_; } |
||||
void EndSpan() { span_.End(); } |
||||
|
||||
private: |
||||
::opencensus::trace::Span span_; |
||||
}; |
||||
|
||||
// Serializes the outgoing trace context. Field IDs are 1 byte followed by
|
||||
// field data. A 1 byte version ID is always encoded first.
|
||||
size_t TraceContextSerialize(const ::opencensus::trace::SpanContext& context, |
||||
char* tracing_buf, size_t tracing_buf_size); |
||||
|
||||
// Serializes the outgoing stats context. Field IDs are 1 byte followed by
|
||||
// field data. A 1 byte version ID is always encoded first. Tags are directly
|
||||
// serialized into the given grpc_slice.
|
||||
size_t StatsContextSerialize(size_t max_tags_len, grpc_slice* tags); |
||||
|
||||
// Serialize outgoing server stats. Returns the number of bytes serialized.
|
||||
size_t ServerStatsSerialize(uint64_t server_elapsed_time, char* buf, |
||||
size_t buf_size); |
||||
|
||||
// Deserialize incoming server stats. Returns the number of bytes deserialized.
|
||||
size_t ServerStatsDeserialize(const char* buf, size_t buf_size, |
||||
uint64_t* server_elapsed_time); |
||||
|
||||
// Deserialize the incoming SpanContext and generate a new server context based
|
||||
// on that. This new span will never be a root span. This should only be called
|
||||
// with a blank CensusContext as it overwrites it.
|
||||
void GenerateServerContext(absl::string_view tracing, absl::string_view stats, |
||||
absl::string_view primary_role, |
||||
absl::string_view method, CensusContext* context); |
||||
|
||||
// Creates a new client context that is by default a new root context.
|
||||
// If the current context is the default context then the newly created
|
||||
// span automatically becomes a root span. This should only be called with a
|
||||
// blank CensusContext as it overwrites it.
|
||||
void GenerateClientContext(absl::string_view method, CensusContext* ctxt, |
||||
CensusContext* parent_ctx); |
||||
|
||||
// Returns the incoming data size from the grpc call final info.
|
||||
uint64_t GetIncomingDataSize(const grpc_call_final_info* final_info); |
||||
|
||||
// Returns the outgoing data size from the grpc call final info.
|
||||
uint64_t GetOutgoingDataSize(const grpc_call_final_info* final_info); |
||||
|
||||
// These helper functions return the SpanContext and Span, respectively
|
||||
// associated with the census_context* stored by grpc. The user will need to
|
||||
// call this for manual propagation of tracing data.
|
||||
::opencensus::trace::SpanContext SpanContextFromCensusContext( |
||||
const census_context* ctxt); |
||||
::opencensus::trace::Span SpanFromCensusContext(const census_context* ctxt); |
||||
|
||||
// Returns a string representation of the StatusCode enum.
|
||||
absl::string_view StatusCodeToString(grpc_status_code code); |
||||
|
||||
inline absl::string_view GetMethod(const grpc_slice* path) { |
||||
if (GRPC_SLICE_IS_EMPTY(*path)) { |
||||
return ""; |
||||
} |
||||
// Check for leading '/' and trim it if present.
|
||||
return absl::StripPrefix(absl::string_view(reinterpret_cast<const char*>( |
||||
GRPC_SLICE_START_PTR(*path)), |
||||
GRPC_SLICE_LENGTH(*path)), |
||||
"/"); |
||||
} |
||||
|
||||
} // namespace grpc
|
||||
|
||||
#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CONTEXT_H */ |
@ -0,0 +1,130 @@ |
||||
/*
|
||||
* |
||||
* 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 <grpc/support/port_platform.h> |
||||
|
||||
#include "src/cpp/ext/filters/census/grpc_plugin.h" |
||||
|
||||
#include <grpcpp/server_context.h> |
||||
|
||||
#include "opencensus/trace/span.h" |
||||
#include "src/cpp/ext/filters/census/channel_filter.h" |
||||
#include "src/cpp/ext/filters/census/client_filter.h" |
||||
#include "src/cpp/ext/filters/census/measures.h" |
||||
#include "src/cpp/ext/filters/census/server_filter.h" |
||||
|
||||
namespace grpc { |
||||
|
||||
void RegisterOpenCensusPlugin() { |
||||
RegisterChannelFilter<CensusChannelData, CensusClientCallData>( |
||||
"opencensus_client", GRPC_CLIENT_CHANNEL, INT_MAX /* priority */, |
||||
nullptr /* condition function */); |
||||
RegisterChannelFilter<CensusChannelData, CensusServerCallData>( |
||||
"opencensus_server", GRPC_SERVER_CHANNEL, INT_MAX /* priority */, |
||||
nullptr /* condition function */); |
||||
|
||||
// Access measures to ensure they are initialized. Otherwise, creating a view
|
||||
// before the first RPC would cause an error.
|
||||
RpcClientSentBytesPerRpc(); |
||||
RpcClientReceivedBytesPerRpc(); |
||||
RpcClientRoundtripLatency(); |
||||
RpcClientServerLatency(); |
||||
RpcClientSentMessagesPerRpc(); |
||||
RpcClientReceivedMessagesPerRpc(); |
||||
|
||||
RpcServerSentBytesPerRpc(); |
||||
RpcServerReceivedBytesPerRpc(); |
||||
RpcServerServerLatency(); |
||||
RpcServerSentMessagesPerRpc(); |
||||
RpcServerReceivedMessagesPerRpc(); |
||||
} |
||||
|
||||
::opencensus::trace::Span GetSpanFromServerContext(ServerContext* context) { |
||||
return reinterpret_cast<const CensusContext*>(context->census_context()) |
||||
->Span(); |
||||
} |
||||
|
||||
// These measure definitions should be kept in sync across opencensus
|
||||
// implementations--see
|
||||
// https://github.com/census-instrumentation/opencensus-java/blob/master/contrib/grpc_metrics/src/main/java/io/opencensus/contrib/grpc/metrics/RpcMeasureConstants.java.
|
||||
::opencensus::stats::TagKey ClientMethodTagKey() { |
||||
static const auto method_tag_key = |
||||
::opencensus::stats::TagKey::Register("grpc_client_method"); |
||||
return method_tag_key; |
||||
} |
||||
|
||||
::opencensus::stats::TagKey ClientStatusTagKey() { |
||||
static const auto status_tag_key = |
||||
::opencensus::stats::TagKey::Register("grpc_client_status"); |
||||
return status_tag_key; |
||||
} |
||||
|
||||
::opencensus::stats::TagKey ServerMethodTagKey() { |
||||
static const auto method_tag_key = |
||||
::opencensus::stats::TagKey::Register("grpc_server_method"); |
||||
return method_tag_key; |
||||
} |
||||
|
||||
::opencensus::stats::TagKey ServerStatusTagKey() { |
||||
static const auto status_tag_key = |
||||
::opencensus::stats::TagKey::Register("grpc_server_status"); |
||||
return status_tag_key; |
||||
} |
||||
|
||||
// Client
|
||||
ABSL_CONST_INIT const absl::string_view |
||||
kRpcClientSentMessagesPerRpcMeasureName = |
||||
"grpc.io/client/sent_messages_per_rpc"; |
||||
|
||||
ABSL_CONST_INIT const absl::string_view kRpcClientSentBytesPerRpcMeasureName = |
||||
"grpc.io/client/sent_bytes_per_rpc"; |
||||
|
||||
ABSL_CONST_INIT const absl::string_view |
||||
kRpcClientReceivedMessagesPerRpcMeasureName = |
||||
"grpc.io/client/received_messages_per_rpc"; |
||||
|
||||
ABSL_CONST_INIT const absl::string_view |
||||
kRpcClientReceivedBytesPerRpcMeasureName = |
||||
"grpc.io/client/received_bytes_per_rpc"; |
||||
|
||||
ABSL_CONST_INIT const absl::string_view kRpcClientRoundtripLatencyMeasureName = |
||||
"grpc.io/client/roundtrip_latency"; |
||||
|
||||
ABSL_CONST_INIT const absl::string_view kRpcClientServerLatencyMeasureName = |
||||
"grpc.io/client/server_latency"; |
||||
|
||||
// Server
|
||||
ABSL_CONST_INIT const absl::string_view |
||||
kRpcServerSentMessagesPerRpcMeasureName = |
||||
"grpc.io/server/sent_messages_per_rpc"; |
||||
|
||||
ABSL_CONST_INIT const absl::string_view kRpcServerSentBytesPerRpcMeasureName = |
||||
"grpc.io/server/sent_bytes_per_rpc"; |
||||
|
||||
ABSL_CONST_INIT const absl::string_view |
||||
kRpcServerReceivedMessagesPerRpcMeasureName = |
||||
"grpc.io/server/received_messages_per_rpc"; |
||||
|
||||
ABSL_CONST_INIT const absl::string_view |
||||
kRpcServerReceivedBytesPerRpcMeasureName = |
||||
"grpc.io/server/received_bytes_per_rpc"; |
||||
|
||||
ABSL_CONST_INIT const absl::string_view kRpcServerServerLatencyMeasureName = |
||||
"grpc.io/server/server_latency"; |
||||
|
||||
} // namespace grpc
|
@ -0,0 +1,111 @@ |
||||
/*
|
||||
* |
||||
* 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_INTERNAL_CPP_EXT_FILTERS_CENSUS_GRPC_PLUGIN_H |
||||
#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_GRPC_PLUGIN_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "absl/strings/string_view.h" |
||||
#include "include/grpcpp/opencensus.h" |
||||
#include "opencensus/stats/stats.h" |
||||
#include "opencensus/trace/span.h" |
||||
|
||||
namespace grpc { |
||||
|
||||
class ServerContext; |
||||
|
||||
// Returns the tracing Span for the current RPC.
|
||||
::opencensus::trace::Span GetSpanFromServerContext(ServerContext* context); |
||||
|
||||
// The tag keys set when recording RPC stats.
|
||||
::opencensus::stats::TagKey ClientMethodTagKey(); |
||||
::opencensus::stats::TagKey ClientStatusTagKey(); |
||||
::opencensus::stats::TagKey ServerMethodTagKey(); |
||||
::opencensus::stats::TagKey ServerStatusTagKey(); |
||||
|
||||
// Names of measures used by the plugin--users can create views on these
|
||||
// measures but should not record data for them.
|
||||
extern const absl::string_view kRpcClientSentMessagesPerRpcMeasureName; |
||||
extern const absl::string_view kRpcClientSentBytesPerRpcMeasureName; |
||||
extern const absl::string_view kRpcClientReceivedMessagesPerRpcMeasureName; |
||||
extern const absl::string_view kRpcClientReceivedBytesPerRpcMeasureName; |
||||
extern const absl::string_view kRpcClientRoundtripLatencyMeasureName; |
||||
extern const absl::string_view kRpcClientServerLatencyMeasureName; |
||||
|
||||
extern const absl::string_view kRpcServerSentMessagesPerRpcMeasureName; |
||||
extern const absl::string_view kRpcServerSentBytesPerRpcMeasureName; |
||||
extern const absl::string_view kRpcServerReceivedMessagesPerRpcMeasureName; |
||||
extern const absl::string_view kRpcServerReceivedBytesPerRpcMeasureName; |
||||
extern const absl::string_view kRpcServerServerLatencyMeasureName; |
||||
|
||||
// Canonical gRPC view definitions.
|
||||
const ::opencensus::stats::ViewDescriptor& ClientSentMessagesPerRpcCumulative(); |
||||
const ::opencensus::stats::ViewDescriptor& ClientSentBytesPerRpcCumulative(); |
||||
const ::opencensus::stats::ViewDescriptor& |
||||
ClientReceivedMessagesPerRpcCumulative(); |
||||
const ::opencensus::stats::ViewDescriptor& |
||||
ClientReceivedBytesPerRpcCumulative(); |
||||
const ::opencensus::stats::ViewDescriptor& ClientRoundtripLatencyCumulative(); |
||||
const ::opencensus::stats::ViewDescriptor& ClientServerLatencyCumulative(); |
||||
const ::opencensus::stats::ViewDescriptor& ClientCompletedRpcsCumulative(); |
||||
|
||||
const ::opencensus::stats::ViewDescriptor& ServerSentBytesPerRpcCumulative(); |
||||
const ::opencensus::stats::ViewDescriptor& |
||||
ServerReceivedBytesPerRpcCumulative(); |
||||
const ::opencensus::stats::ViewDescriptor& ServerServerLatencyCumulative(); |
||||
const ::opencensus::stats::ViewDescriptor& ServerStartedCountCumulative(); |
||||
const ::opencensus::stats::ViewDescriptor& ServerCompletedRpcsCumulative(); |
||||
const ::opencensus::stats::ViewDescriptor& ServerSentMessagesPerRpcCumulative(); |
||||
const ::opencensus::stats::ViewDescriptor& |
||||
ServerReceivedMessagesPerRpcCumulative(); |
||||
|
||||
const ::opencensus::stats::ViewDescriptor& ClientSentMessagesPerRpcMinute(); |
||||
const ::opencensus::stats::ViewDescriptor& ClientSentBytesPerRpcMinute(); |
||||
const ::opencensus::stats::ViewDescriptor& ClientReceivedMessagesPerRpcMinute(); |
||||
const ::opencensus::stats::ViewDescriptor& ClientReceivedBytesPerRpcMinute(); |
||||
const ::opencensus::stats::ViewDescriptor& ClientRoundtripLatencyMinute(); |
||||
const ::opencensus::stats::ViewDescriptor& ClientServerLatencyMinute(); |
||||
const ::opencensus::stats::ViewDescriptor& ClientCompletedRpcsMinute(); |
||||
|
||||
const ::opencensus::stats::ViewDescriptor& ServerSentMessagesPerRpcMinute(); |
||||
const ::opencensus::stats::ViewDescriptor& ServerSentBytesPerRpcMinute(); |
||||
const ::opencensus::stats::ViewDescriptor& ServerReceivedMessagesPerRpcMinute(); |
||||
const ::opencensus::stats::ViewDescriptor& ServerReceivedBytesPerRpcMinute(); |
||||
const ::opencensus::stats::ViewDescriptor& ServerServerLatencyMinute(); |
||||
const ::opencensus::stats::ViewDescriptor& ServerCompletedRpcsMinute(); |
||||
|
||||
const ::opencensus::stats::ViewDescriptor& ClientSentMessagesPerRpcHour(); |
||||
const ::opencensus::stats::ViewDescriptor& ClientSentBytesPerRpcHour(); |
||||
const ::opencensus::stats::ViewDescriptor& ClientReceivedMessagesPerRpcHour(); |
||||
const ::opencensus::stats::ViewDescriptor& ClientReceivedBytesPerRpcHour(); |
||||
const ::opencensus::stats::ViewDescriptor& ClientRoundtripLatencyHour(); |
||||
const ::opencensus::stats::ViewDescriptor& ClientServerLatencyHour(); |
||||
const ::opencensus::stats::ViewDescriptor& ClientCompletedRpcsHour(); |
||||
|
||||
const ::opencensus::stats::ViewDescriptor& ServerSentMessagesPerRpcHour(); |
||||
const ::opencensus::stats::ViewDescriptor& ServerSentBytesPerRpcHour(); |
||||
const ::opencensus::stats::ViewDescriptor& ServerReceivedMessagesPerRpcHour(); |
||||
const ::opencensus::stats::ViewDescriptor& ServerReceivedBytesPerRpcHour(); |
||||
const ::opencensus::stats::ViewDescriptor& ServerServerLatencyHour(); |
||||
const ::opencensus::stats::ViewDescriptor& ServerStartedCountHour(); |
||||
const ::opencensus::stats::ViewDescriptor& ServerCompletedRpcsHour(); |
||||
|
||||
} // namespace grpc
|
||||
|
||||
#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_GRPC_PLUGIN_H */ |
@ -0,0 +1,129 @@ |
||||
/*
|
||||
* |
||||
* 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 <grpc/support/port_platform.h> |
||||
|
||||
#include "src/cpp/ext/filters/census/measures.h" |
||||
|
||||
#include "opencensus/stats/stats.h" |
||||
#include "src/cpp/ext/filters/census/grpc_plugin.h" |
||||
|
||||
namespace grpc { |
||||
|
||||
using ::opencensus::stats::MeasureDouble; |
||||
using ::opencensus::stats::MeasureInt64; |
||||
|
||||
// These measure definitions should be kept in sync across opencensus
|
||||
// implementations--see
|
||||
// https://github.com/census-instrumentation/opencensus-java/blob/master/contrib/grpc_metrics/src/main/java/io/opencensus/contrib/grpc/metrics/RpcMeasureConstants.java.
|
||||
|
||||
namespace { |
||||
|
||||
// Unit constants
|
||||
constexpr char kUnitBytes[] = "By"; |
||||
constexpr char kUnitMilliseconds[] = "ms"; |
||||
constexpr char kCount[] = "1"; |
||||
|
||||
} // namespace
|
||||
|
||||
// Client
|
||||
MeasureDouble RpcClientSentBytesPerRpc() { |
||||
static const auto measure = MeasureDouble::Register( |
||||
kRpcClientSentBytesPerRpcMeasureName, |
||||
"Total bytes sent across all request messages per RPC", kUnitBytes); |
||||
return measure; |
||||
} |
||||
|
||||
MeasureDouble RpcClientReceivedBytesPerRpc() { |
||||
static const auto measure = MeasureDouble::Register( |
||||
kRpcClientReceivedBytesPerRpcMeasureName, |
||||
"Total bytes received across all response messages per RPC", kUnitBytes); |
||||
return measure; |
||||
} |
||||
|
||||
MeasureDouble RpcClientRoundtripLatency() { |
||||
static const auto measure = MeasureDouble::Register( |
||||
kRpcClientRoundtripLatencyMeasureName, |
||||
"Time between first byte of request sent to last byte of response " |
||||
"received, or terminal error", |
||||
kUnitMilliseconds); |
||||
return measure; |
||||
} |
||||
|
||||
MeasureDouble RpcClientServerLatency() { |
||||
static const auto measure = MeasureDouble::Register( |
||||
kRpcClientServerLatencyMeasureName, |
||||
"Time between first byte of request received to last byte of response " |
||||
"sent, or terminal error (propagated from the server)", |
||||
kUnitMilliseconds); |
||||
return measure; |
||||
} |
||||
|
||||
MeasureInt64 RpcClientSentMessagesPerRpc() { |
||||
static const auto measure = |
||||
MeasureInt64::Register(kRpcClientSentMessagesPerRpcMeasureName, |
||||
"Number of messages sent per RPC", kCount); |
||||
return measure; |
||||
} |
||||
|
||||
MeasureInt64 RpcClientReceivedMessagesPerRpc() { |
||||
static const auto measure = |
||||
MeasureInt64::Register(kRpcClientReceivedMessagesPerRpcMeasureName, |
||||
"Number of messages received per RPC", kCount); |
||||
return measure; |
||||
} |
||||
|
||||
// Server
|
||||
MeasureDouble RpcServerSentBytesPerRpc() { |
||||
static const auto measure = MeasureDouble::Register( |
||||
kRpcServerSentBytesPerRpcMeasureName, |
||||
"Total bytes sent across all messages per RPC", kUnitBytes); |
||||
return measure; |
||||
} |
||||
|
||||
MeasureDouble RpcServerReceivedBytesPerRpc() { |
||||
static const auto measure = MeasureDouble::Register( |
||||
kRpcServerReceivedBytesPerRpcMeasureName, |
||||
"Total bytes received across all messages per RPC", kUnitBytes); |
||||
return measure; |
||||
} |
||||
|
||||
MeasureDouble RpcServerServerLatency() { |
||||
static const auto measure = MeasureDouble::Register( |
||||
kRpcServerServerLatencyMeasureName, |
||||
"Time between first byte of request received to last byte of response " |
||||
"sent, or terminal error", |
||||
kUnitMilliseconds); |
||||
return measure; |
||||
} |
||||
|
||||
MeasureInt64 RpcServerSentMessagesPerRpc() { |
||||
static const auto measure = |
||||
MeasureInt64::Register(kRpcServerSentMessagesPerRpcMeasureName, |
||||
"Number of messages sent per RPC", kCount); |
||||
return measure; |
||||
} |
||||
|
||||
MeasureInt64 RpcServerReceivedMessagesPerRpc() { |
||||
static const auto measure = |
||||
MeasureInt64::Register(kRpcServerReceivedMessagesPerRpcMeasureName, |
||||
"Number of messages received per RPC", kCount); |
||||
return measure; |
||||
} |
||||
|
||||
} // namespace grpc
|
@ -0,0 +1,46 @@ |
||||
/*
|
||||
* |
||||
* 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_INTERNAL_CPP_EXT_FILTERS_CENSUS_MEASURES_H |
||||
#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_MEASURES_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "opencensus/stats/stats.h" |
||||
#include "src/cpp/ext/filters/census/grpc_plugin.h" |
||||
|
||||
namespace grpc { |
||||
|
||||
::opencensus::stats::MeasureInt64 RpcClientSentMessagesPerRpc(); |
||||
::opencensus::stats::MeasureDouble RpcClientSentBytesPerRpc(); |
||||
::opencensus::stats::MeasureInt64 RpcClientReceivedMessagesPerRpc(); |
||||
::opencensus::stats::MeasureDouble RpcClientReceivedBytesPerRpc(); |
||||
::opencensus::stats::MeasureDouble RpcClientRoundtripLatency(); |
||||
::opencensus::stats::MeasureDouble RpcClientServerLatency(); |
||||
::opencensus::stats::MeasureInt64 RpcClientCompletedRpcs(); |
||||
|
||||
::opencensus::stats::MeasureInt64 RpcServerSentMessagesPerRpc(); |
||||
::opencensus::stats::MeasureDouble RpcServerSentBytesPerRpc(); |
||||
::opencensus::stats::MeasureInt64 RpcServerReceivedMessagesPerRpc(); |
||||
::opencensus::stats::MeasureDouble RpcServerReceivedBytesPerRpc(); |
||||
::opencensus::stats::MeasureDouble RpcServerServerLatency(); |
||||
::opencensus::stats::MeasureInt64 RpcServerCompletedRpcs(); |
||||
|
||||
} // namespace grpc
|
||||
|
||||
#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_MEASURES_H */ |
@ -0,0 +1,39 @@ |
||||
/*
|
||||
* |
||||
* 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 <grpc/support/port_platform.h> |
||||
|
||||
#include "src/cpp/ext/filters/census/rpc_encoding.h" |
||||
|
||||
namespace grpc { |
||||
|
||||
constexpr size_t TraceContextEncoding::kGrpcTraceContextSize; |
||||
constexpr size_t TraceContextEncoding::kEncodeDecodeFailure; |
||||
constexpr size_t TraceContextEncoding::kVersionIdSize; |
||||
constexpr size_t TraceContextEncoding::kFieldIdSize; |
||||
constexpr size_t TraceContextEncoding::kVersionIdOffset; |
||||
constexpr size_t TraceContextEncoding::kVersionId; |
||||
|
||||
constexpr size_t RpcServerStatsEncoding::kRpcServerStatsSize; |
||||
constexpr size_t RpcServerStatsEncoding::kEncodeDecodeFailure; |
||||
constexpr size_t RpcServerStatsEncoding::kVersionIdSize; |
||||
constexpr size_t RpcServerStatsEncoding::kFieldIdSize; |
||||
constexpr size_t RpcServerStatsEncoding::kVersionIdOffset; |
||||
constexpr size_t RpcServerStatsEncoding::kVersionId; |
||||
|
||||
} // namespace grpc
|
@ -0,0 +1,284 @@ |
||||
/*
|
||||
* |
||||
* 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_INTERNAL_CPP_EXT_FILTERS_CENSUS_RPC_ENCODING_H |
||||
#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_RPC_ENCODING_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include <string.h> |
||||
|
||||
#include "absl/base/internal/endian.h" |
||||
#include "absl/strings/string_view.h" |
||||
#include "opencensus/trace/span_context.h" |
||||
#include "opencensus/trace/span_id.h" |
||||
#include "opencensus/trace/trace_id.h" |
||||
|
||||
namespace grpc { |
||||
|
||||
// TODO: Rename to GrpcTraceContextV0.
|
||||
struct GrpcTraceContext { |
||||
GrpcTraceContext() {} |
||||
|
||||
explicit GrpcTraceContext(const ::opencensus::trace::SpanContext& ctx) { |
||||
ctx.trace_id().CopyTo(trace_id); |
||||
ctx.span_id().CopyTo(span_id); |
||||
ctx.trace_options().CopyTo(trace_options); |
||||
} |
||||
|
||||
::opencensus::trace::SpanContext ToSpanContext() const { |
||||
return ::opencensus::trace::SpanContext( |
||||
::opencensus::trace::TraceId(trace_id), |
||||
::opencensus::trace::SpanId(span_id), |
||||
::opencensus::trace::TraceOptions(trace_options)); |
||||
} |
||||
|
||||
// TODO: For performance:
|
||||
// uint8_t version;
|
||||
// uint8_t trace_id_field_id;
|
||||
uint8_t trace_id[::opencensus::trace::TraceId::kSize]; |
||||
// uint8_t span_id_field_id;
|
||||
uint8_t span_id[::opencensus::trace::SpanId::kSize]; |
||||
// uint8_t trace_options_field_id;
|
||||
uint8_t trace_options[::opencensus::trace::TraceOptions::kSize]; |
||||
}; |
||||
|
||||
// TraceContextEncoding encapsulates the logic for encoding and decoding of
|
||||
// trace contexts.
|
||||
class TraceContextEncoding { |
||||
public: |
||||
// Size of encoded GrpcTraceContext. (16 + 8 + 1 + 4)
|
||||
static constexpr size_t kGrpcTraceContextSize = 29; |
||||
// Error value.
|
||||
static constexpr size_t kEncodeDecodeFailure = 0; |
||||
|
||||
// Deserializes a GrpcTraceContext from the incoming buffer. Returns the
|
||||
// number of bytes deserialized from the buffer. If the incoming buffer is
|
||||
// empty or the encoding version is not supported it will return 0 bytes,
|
||||
// currently only version 0 is supported. If an unknown field ID is
|
||||
// encountered it will return immediately without parsing the rest of the
|
||||
// buffer. Inlined for performance reasons.
|
||||
static size_t Decode(absl::string_view buf, GrpcTraceContext* tc) { |
||||
if (buf.empty()) { |
||||
return kEncodeDecodeFailure; |
||||
} |
||||
uint8_t version = buf[kVersionIdOffset]; |
||||
// TODO: Support other versions later. Only support version 0 for
|
||||
// now.
|
||||
if (version != kVersionId) { |
||||
return kEncodeDecodeFailure; |
||||
} |
||||
|
||||
size_t pos = kVersionIdSize; |
||||
while (pos < buf.size()) { |
||||
size_t bytes_read = |
||||
ParseField(absl::string_view(&buf[pos], buf.size() - pos), tc); |
||||
if (bytes_read == 0) { |
||||
break; |
||||
} else { |
||||
pos += bytes_read; |
||||
} |
||||
} |
||||
return pos; |
||||
} |
||||
|
||||
// Serializes a GrpcTraceContext into the provided buffer. Returns the number
|
||||
// of bytes serialized into the buffer. If the buffer is not of sufficient
|
||||
// size (it must be at least kGrpcTraceContextSize bytes) it will drop
|
||||
// everything and return 0 bytes serialized. Inlined for performance reasons.
|
||||
static size_t Encode(const GrpcTraceContext& tc, char* buf, size_t buf_size) { |
||||
if (buf_size < kGrpcTraceContextSize) { |
||||
return kEncodeDecodeFailure; |
||||
} |
||||
buf[kVersionIdOffset] = kVersionId; |
||||
buf[kTraceIdOffset] = kTraceIdField; |
||||
memcpy(&buf[kTraceIdOffset + 1], tc.trace_id, |
||||
opencensus::trace::TraceId::kSize); |
||||
buf[kSpanIdOffset] = kSpanIdField; |
||||
memcpy(&buf[kSpanIdOffset + 1], tc.span_id, |
||||
opencensus::trace::SpanId::kSize); |
||||
buf[kTraceOptionsOffset] = kTraceOptionsField; |
||||
memcpy(&buf[kTraceOptionsOffset + 1], tc.trace_options, |
||||
opencensus::trace::TraceOptions::kSize); |
||||
return kGrpcTraceContextSize; |
||||
} |
||||
|
||||
private: |
||||
// Parses the next field from the incoming buffer and stores the parsed value
|
||||
// in a GrpcTraceContext struct. If it does not recognize the field ID it
|
||||
// will return 0, otherwise it returns the number of bytes read.
|
||||
static size_t ParseField(absl::string_view buf, GrpcTraceContext* tc) { |
||||
// TODO: Add support for multi-byte field IDs.
|
||||
if (buf.empty()) { |
||||
return 0; |
||||
} |
||||
// Field ID is always the first byte in a field.
|
||||
uint32_t field_id = buf[0]; |
||||
size_t bytes_read = kFieldIdSize; |
||||
switch (field_id) { |
||||
case kTraceIdField: |
||||
bytes_read += kTraceIdSize; |
||||
if (bytes_read > buf.size()) { |
||||
return 0; |
||||
} |
||||
memcpy(tc->trace_id, &buf[kFieldIdSize], |
||||
opencensus::trace::TraceId::kSize); |
||||
break; |
||||
case kSpanIdField: |
||||
bytes_read += kSpanIdSize; |
||||
if (bytes_read > buf.size()) { |
||||
return 0; |
||||
} |
||||
memcpy(tc->span_id, &buf[kFieldIdSize], |
||||
opencensus::trace::SpanId::kSize); |
||||
break; |
||||
case kTraceOptionsField: |
||||
bytes_read += kTraceOptionsSize; |
||||
if (bytes_read > buf.size()) { |
||||
return 0; |
||||
} |
||||
memcpy(tc->trace_options, &buf[kFieldIdSize], |
||||
opencensus::trace::TraceOptions::kSize); |
||||
break; |
||||
default: // Invalid field ID
|
||||
return 0; |
||||
} |
||||
|
||||
return bytes_read; |
||||
} |
||||
|
||||
// Size of Version ID.
|
||||
static constexpr size_t kVersionIdSize = 1; |
||||
// Size of Field ID.
|
||||
static constexpr size_t kFieldIdSize = 1; |
||||
|
||||
// Offset and value for currently supported version ID.
|
||||
static constexpr size_t kVersionIdOffset = 0; |
||||
static constexpr size_t kVersionId = 0; |
||||
|
||||
// Fixed Field ID values:
|
||||
enum FieldIdValue { |
||||
kTraceIdField = 0, |
||||
kSpanIdField = 1, |
||||
kTraceOptionsField = 2, |
||||
}; |
||||
|
||||
// Field data sizes in bytes
|
||||
enum FieldSize { |
||||
kTraceIdSize = 16, |
||||
kSpanIdSize = 8, |
||||
kTraceOptionsSize = 1, |
||||
}; |
||||
|
||||
// Fixed size offsets for field ID start positions during encoding. Field
|
||||
// data immediately follows.
|
||||
enum FieldIdOffset { |
||||
kTraceIdOffset = kVersionIdSize, |
||||
kSpanIdOffset = kTraceIdOffset + kFieldIdSize + kTraceIdSize, |
||||
kTraceOptionsOffset = kSpanIdOffset + kFieldIdSize + kSpanIdSize, |
||||
}; |
||||
|
||||
TraceContextEncoding() = delete; |
||||
TraceContextEncoding(const TraceContextEncoding&) = delete; |
||||
TraceContextEncoding(TraceContextEncoding&&) = delete; |
||||
TraceContextEncoding operator=(const TraceContextEncoding&) = delete; |
||||
TraceContextEncoding operator=(TraceContextEncoding&&) = delete; |
||||
}; |
||||
|
||||
// TODO: This may not be needed. Check to see if opencensus requires
|
||||
// a trailing server response.
|
||||
// RpcServerStatsEncoding encapsulates the logic for encoding and decoding of
|
||||
// rpc server stats messages. Rpc server stats consists of a uint64_t time
|
||||
// value (server latency in nanoseconds).
|
||||
class RpcServerStatsEncoding { |
||||
public: |
||||
// Size of encoded RPC server stats.
|
||||
static constexpr size_t kRpcServerStatsSize = 10; |
||||
// Error value.
|
||||
static constexpr size_t kEncodeDecodeFailure = 0; |
||||
|
||||
// Deserializes rpc server stats from the incoming 'buf' into *time. Returns
|
||||
// number of bytes decoded. If the buffer is of insufficient size (it must be
|
||||
// at least kRpcServerStatsSize bytes) or the encoding version or field ID are
|
||||
// unrecognized, *time will be set to 0 and it will return
|
||||
// kEncodeDecodeFailure. Inlined for performance reasons.
|
||||
static size_t Decode(absl::string_view buf, uint64_t* time) { |
||||
if (buf.size() < kRpcServerStatsSize) { |
||||
*time = 0; |
||||
return kEncodeDecodeFailure; |
||||
} |
||||
|
||||
uint8_t version = buf[kVersionIdOffset]; |
||||
uint32_t fieldID = buf[kServerElapsedTimeOffset]; |
||||
if (version != kVersionId || fieldID != kServerElapsedTimeField) { |
||||
*time = 0; |
||||
return kEncodeDecodeFailure; |
||||
} |
||||
*time = absl::little_endian::Load64( |
||||
&buf[kServerElapsedTimeOffset + kFieldIdSize]); |
||||
return kRpcServerStatsSize; |
||||
} |
||||
|
||||
// Serializes rpc server stats into the provided buffer. It returns the
|
||||
// number of bytes written to the buffer. If the buffer is smaller than
|
||||
// kRpcServerStatsSize bytes it will return kEncodeDecodeFailure. Inlined for
|
||||
// performance reasons.
|
||||
static size_t Encode(uint64_t time, char* buf, size_t buf_size) { |
||||
if (buf_size < kRpcServerStatsSize) { |
||||
return kEncodeDecodeFailure; |
||||
} |
||||
|
||||
buf[kVersionIdOffset] = kVersionId; |
||||
buf[kServerElapsedTimeOffset] = kServerElapsedTimeField; |
||||
absl::little_endian::Store64(&buf[kServerElapsedTimeOffset + kFieldIdSize], |
||||
time); |
||||
return kRpcServerStatsSize; |
||||
} |
||||
|
||||
private: |
||||
// Size of Version ID.
|
||||
static constexpr size_t kVersionIdSize = 1; |
||||
// Size of Field ID.
|
||||
static constexpr size_t kFieldIdSize = 1; |
||||
|
||||
// Offset and value for currently supported version ID.
|
||||
static constexpr size_t kVersionIdOffset = 0; |
||||
static constexpr size_t kVersionId = 0; |
||||
|
||||
enum FieldIdValue { |
||||
kServerElapsedTimeField = 0, |
||||
}; |
||||
|
||||
enum FieldSize { |
||||
kServerElapsedTimeSize = 8, |
||||
}; |
||||
|
||||
enum FieldIdOffset { |
||||
kServerElapsedTimeOffset = kVersionIdSize, |
||||
}; |
||||
|
||||
RpcServerStatsEncoding() = delete; |
||||
RpcServerStatsEncoding(const RpcServerStatsEncoding&) = delete; |
||||
RpcServerStatsEncoding(RpcServerStatsEncoding&&) = delete; |
||||
RpcServerStatsEncoding operator=(const RpcServerStatsEncoding&) = delete; |
||||
RpcServerStatsEncoding operator=(RpcServerStatsEncoding&&) = delete; |
||||
}; |
||||
|
||||
} // namespace grpc
|
||||
|
||||
#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_RPC_ENCODING_H */ |
@ -0,0 +1,198 @@ |
||||
/*
|
||||
* |
||||
* 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 <grpc/support/port_platform.h> |
||||
|
||||
#include "src/cpp/ext/filters/census/server_filter.h" |
||||
|
||||
#include "absl/strings/str_cat.h" |
||||
#include "absl/strings/string_view.h" |
||||
#include "absl/time/clock.h" |
||||
#include "absl/time/time.h" |
||||
#include "opencensus/stats/stats.h" |
||||
#include "src/core/lib/surface/call.h" |
||||
#include "src/cpp/ext/filters/census/grpc_plugin.h" |
||||
#include "src/cpp/ext/filters/census/measures.h" |
||||
|
||||
namespace grpc { |
||||
|
||||
constexpr uint32_t CensusServerCallData::kMaxServerStatsLen; |
||||
|
||||
namespace { |
||||
|
||||
// server metadata elements
|
||||
struct ServerMetadataElements { |
||||
grpc_slice path; |
||||
grpc_slice tracing_slice; |
||||
grpc_slice census_proto; |
||||
}; |
||||
|
||||
void FilterInitialMetadata(grpc_metadata_batch* b, |
||||
ServerMetadataElements* sml) { |
||||
if (b->idx.named.path != nullptr) { |
||||
sml->path = grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.path->md)); |
||||
} |
||||
if (b->idx.named.grpc_trace_bin != nullptr) { |
||||
sml->tracing_slice = |
||||
grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.grpc_trace_bin->md)); |
||||
grpc_metadata_batch_remove(b, b->idx.named.grpc_trace_bin); |
||||
} |
||||
if (b->idx.named.grpc_tags_bin != nullptr) { |
||||
sml->census_proto = |
||||
grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.grpc_tags_bin->md)); |
||||
grpc_metadata_batch_remove(b, b->idx.named.grpc_tags_bin); |
||||
} |
||||
} |
||||
|
||||
} // namespace
|
||||
|
||||
void CensusServerCallData::OnDoneRecvMessageCb(void* user_data, |
||||
grpc_error* error) { |
||||
grpc_call_element* elem = reinterpret_cast<grpc_call_element*>(user_data); |
||||
CensusServerCallData* calld = |
||||
reinterpret_cast<CensusServerCallData*>(elem->call_data); |
||||
CensusChannelData* channeld = |
||||
reinterpret_cast<CensusChannelData*>(elem->channel_data); |
||||
GPR_ASSERT(calld != nullptr); |
||||
GPR_ASSERT(channeld != nullptr); |
||||
// Stream messages are no longer valid after receiving trailing metadata.
|
||||
if ((*calld->recv_message_) != nullptr) { |
||||
++calld->recv_message_count_; |
||||
} |
||||
GRPC_CLOSURE_RUN(calld->initial_on_done_recv_message_, GRPC_ERROR_REF(error)); |
||||
} |
||||
|
||||
void CensusServerCallData::OnDoneRecvInitialMetadataCb(void* user_data, |
||||
grpc_error* error) { |
||||
grpc_call_element* elem = reinterpret_cast<grpc_call_element*>(user_data); |
||||
CensusServerCallData* calld = |
||||
reinterpret_cast<CensusServerCallData*>(elem->call_data); |
||||
GPR_ASSERT(calld != nullptr); |
||||
if (error == GRPC_ERROR_NONE) { |
||||
grpc_metadata_batch* initial_metadata = calld->recv_initial_metadata_; |
||||
GPR_ASSERT(initial_metadata != nullptr); |
||||
ServerMetadataElements sml; |
||||
sml.path = grpc_empty_slice(); |
||||
sml.tracing_slice = grpc_empty_slice(); |
||||
sml.census_proto = grpc_empty_slice(); |
||||
FilterInitialMetadata(initial_metadata, &sml); |
||||
calld->path_ = grpc_slice_ref_internal(sml.path); |
||||
calld->method_ = GetMethod(&calld->path_); |
||||
calld->qualified_method_ = StrCat("Recv.", calld->method_); |
||||
const char* tracing_str = |
||||
GRPC_SLICE_IS_EMPTY(sml.tracing_slice) |
||||
? "" |
||||
: reinterpret_cast<const char*>( |
||||
GRPC_SLICE_START_PTR(sml.tracing_slice)); |
||||
size_t tracing_str_len = GRPC_SLICE_IS_EMPTY(sml.tracing_slice) |
||||
? 0 |
||||
: GRPC_SLICE_LENGTH(sml.tracing_slice); |
||||
const char* census_str = GRPC_SLICE_IS_EMPTY(sml.census_proto) |
||||
? "" |
||||
: reinterpret_cast<const char*>( |
||||
GRPC_SLICE_START_PTR(sml.census_proto)); |
||||
size_t census_str_len = GRPC_SLICE_IS_EMPTY(sml.census_proto) |
||||
? 0 |
||||
: GRPC_SLICE_LENGTH(sml.census_proto); |
||||
|
||||
GenerateServerContext(absl::string_view(tracing_str, tracing_str_len), |
||||
absl::string_view(census_str, census_str_len), |
||||
/*primary_role*/ "", calld->qualified_method_, |
||||
&calld->context_); |
||||
|
||||
grpc_slice_unref_internal(sml.tracing_slice); |
||||
grpc_slice_unref_internal(sml.census_proto); |
||||
grpc_slice_unref_internal(sml.path); |
||||
grpc_census_call_set_context( |
||||
calld->gc_, reinterpret_cast<census_context*>(&calld->context_)); |
||||
} |
||||
GRPC_CLOSURE_RUN(calld->initial_on_done_recv_initial_metadata_, |
||||
GRPC_ERROR_REF(error)); |
||||
} |
||||
|
||||
void CensusServerCallData::StartTransportStreamOpBatch( |
||||
grpc_call_element* elem, TransportStreamOpBatch* op) { |
||||
if (op->recv_initial_metadata() != nullptr) { |
||||
// substitute our callback for the op callback
|
||||
recv_initial_metadata_ = op->recv_initial_metadata()->batch(); |
||||
initial_on_done_recv_initial_metadata_ = op->recv_initial_metadata_ready(); |
||||
op->set_recv_initial_metadata_ready(&on_done_recv_initial_metadata_); |
||||
} |
||||
if (op->send_message() != nullptr) { |
||||
++sent_message_count_; |
||||
} |
||||
if (op->recv_message() != nullptr) { |
||||
recv_message_ = op->op()->payload->recv_message.recv_message; |
||||
initial_on_done_recv_message_ = |
||||
op->op()->payload->recv_message.recv_message_ready; |
||||
op->op()->payload->recv_message.recv_message_ready = &on_done_recv_message_; |
||||
} |
||||
// We need to record the time when the trailing metadata was sent to mark the
|
||||
// completeness of the request.
|
||||
if (op->send_trailing_metadata() != nullptr) { |
||||
elapsed_time_ = absl::Now() - start_time_; |
||||
size_t len = ServerStatsSerialize(absl::ToInt64Nanoseconds(elapsed_time_), |
||||
stats_buf_, kMaxServerStatsLen); |
||||
if (len > 0) { |
||||
GRPC_LOG_IF_ERROR( |
||||
"census grpc_filter", |
||||
grpc_metadata_batch_add_tail( |
||||
op->send_trailing_metadata()->batch(), &census_bin_, |
||||
grpc_mdelem_from_slices( |
||||
GRPC_MDSTR_GRPC_SERVER_STATS_BIN, |
||||
grpc_slice_from_copied_buffer(stats_buf_, len)))); |
||||
} |
||||
} |
||||
// Call next op.
|
||||
grpc_call_next_op(elem, op->op()); |
||||
} |
||||
|
||||
grpc_error* CensusServerCallData::Init(grpc_call_element* elem, |
||||
const grpc_call_element_args* args) { |
||||
start_time_ = absl::Now(); |
||||
gc_ = |
||||
grpc_call_from_top_element(grpc_call_stack_element(args->call_stack, 0)); |
||||
GRPC_CLOSURE_INIT(&on_done_recv_initial_metadata_, |
||||
OnDoneRecvInitialMetadataCb, elem, |
||||
grpc_schedule_on_exec_ctx); |
||||
GRPC_CLOSURE_INIT(&on_done_recv_message_, OnDoneRecvMessageCb, elem, |
||||
grpc_schedule_on_exec_ctx); |
||||
auth_context_ = grpc_call_auth_context(gc_); |
||||
return GRPC_ERROR_NONE; |
||||
} |
||||
|
||||
void CensusServerCallData::Destroy(grpc_call_element* elem, |
||||
const grpc_call_final_info* final_info, |
||||
grpc_closure* then_call_closure) { |
||||
const uint64_t request_size = GetOutgoingDataSize(final_info); |
||||
const uint64_t response_size = GetIncomingDataSize(final_info); |
||||
double elapsed_time_ms = absl::ToDoubleMilliseconds(elapsed_time_); |
||||
grpc_auth_context_release(auth_context_); |
||||
::opencensus::stats::Record( |
||||
{{RpcServerSentBytesPerRpc(), static_cast<double>(response_size)}, |
||||
{RpcServerReceivedBytesPerRpc(), static_cast<double>(request_size)}, |
||||
{RpcServerServerLatency(), elapsed_time_ms}, |
||||
{RpcServerSentMessagesPerRpc(), sent_message_count_}, |
||||
{RpcServerReceivedMessagesPerRpc(), recv_message_count_}}, |
||||
{{ServerMethodTagKey(), method_}, |
||||
{ServerStatusTagKey(), StatusCodeToString(final_info->final_status)}}); |
||||
grpc_slice_unref_internal(path_); |
||||
context_.EndSpan(); |
||||
} |
||||
|
||||
} // namespace grpc
|
@ -0,0 +1,101 @@ |
||||
/*
|
||||
* |
||||
* 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_INTERNAL_CPP_EXT_FILTERS_CENSUS_SERVER_FILTER_H |
||||
#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_SERVER_FILTER_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "absl/strings/string_view.h" |
||||
#include "absl/time/clock.h" |
||||
#include "absl/time/time.h" |
||||
#include "include/grpc/grpc_security.h" |
||||
#include "src/cpp/ext/filters/census/channel_filter.h" |
||||
#include "src/cpp/ext/filters/census/context.h" |
||||
|
||||
namespace grpc { |
||||
|
||||
// A CallData class will be created for every grpc call within a channel. It is
|
||||
// used to store data and methods specific to that call. CensusServerCallData is
|
||||
// thread-compatible, however typically only 1 thread should be interacting with
|
||||
// a call at a time.
|
||||
class CensusServerCallData : public CallData { |
||||
public: |
||||
// Maximum size of server stats that are sent on the wire.
|
||||
static constexpr uint32_t kMaxServerStatsLen = 16; |
||||
|
||||
CensusServerCallData() |
||||
: gc_(nullptr), |
||||
auth_context_(nullptr), |
||||
recv_initial_metadata_(nullptr), |
||||
initial_on_done_recv_initial_metadata_(nullptr), |
||||
initial_on_done_recv_message_(nullptr), |
||||
recv_message_(nullptr), |
||||
recv_message_count_(0), |
||||
sent_message_count_(0) { |
||||
memset(&census_bin_, 0, sizeof(grpc_linked_mdelem)); |
||||
memset(&path_, 0, sizeof(grpc_slice)); |
||||
memset(&on_done_recv_initial_metadata_, 0, sizeof(grpc_closure)); |
||||
memset(&on_done_recv_message_, 0, sizeof(grpc_closure)); |
||||
} |
||||
|
||||
grpc_error* Init(grpc_call_element* elem, |
||||
const grpc_call_element_args* args) override; |
||||
|
||||
void Destroy(grpc_call_element* elem, const grpc_call_final_info* final_info, |
||||
grpc_closure* then_call_closure) override; |
||||
|
||||
void StartTransportStreamOpBatch(grpc_call_element* elem, |
||||
TransportStreamOpBatch* op) override; |
||||
|
||||
static void OnDoneRecvInitialMetadataCb(void* user_data, grpc_error* error); |
||||
|
||||
static void OnDoneRecvMessageCb(void* user_data, grpc_error* error); |
||||
|
||||
private: |
||||
CensusContext context_; |
||||
// server method
|
||||
absl::string_view method_; |
||||
std::string qualified_method_; |
||||
grpc_slice path_; |
||||
// Pointer to the grpc_call element
|
||||
grpc_call* gc_; |
||||
// Authorization context for the call.
|
||||
grpc_auth_context* auth_context_; |
||||
// Metadata element for census stats.
|
||||
grpc_linked_mdelem census_bin_; |
||||
// recv callback
|
||||
grpc_metadata_batch* recv_initial_metadata_; |
||||
grpc_closure* initial_on_done_recv_initial_metadata_; |
||||
grpc_closure on_done_recv_initial_metadata_; |
||||
// recv message
|
||||
grpc_closure* initial_on_done_recv_message_; |
||||
grpc_closure on_done_recv_message_; |
||||
absl::Time start_time_; |
||||
absl::Duration elapsed_time_; |
||||
grpc_core::OrphanablePtr<grpc_core::ByteStream>* recv_message_; |
||||
uint64_t recv_message_count_; |
||||
uint64_t sent_message_count_; |
||||
// Buffer needed for grpc_slice to reference it when adding metatdata to
|
||||
// response.
|
||||
char stats_buf_[kMaxServerStatsLen]; |
||||
}; |
||||
|
||||
} // namespace grpc
|
||||
|
||||
#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_SERVER_FILTER_H */ |
@ -0,0 +1,491 @@ |
||||
/*
|
||||
* |
||||
* 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 <grpc/support/port_platform.h> |
||||
|
||||
#include "src/cpp/ext/filters/census/grpc_plugin.h" |
||||
|
||||
#include "absl/time/time.h" |
||||
#include "opencensus/stats/internal/aggregation_window.h" |
||||
#include "opencensus/stats/internal/set_aggregation_window.h" |
||||
#include "opencensus/stats/stats.h" |
||||
|
||||
namespace grpc { |
||||
|
||||
using ::opencensus::stats::Aggregation; |
||||
using ::opencensus::stats::AggregationWindow; |
||||
using ::opencensus::stats::BucketBoundaries; |
||||
using ::opencensus::stats::ViewDescriptor; |
||||
|
||||
// These measure definitions should be kept in sync across opencensus
|
||||
// implementations.
|
||||
|
||||
namespace { |
||||
|
||||
Aggregation BytesDistributionAggregation() { |
||||
return Aggregation::Distribution(BucketBoundaries::Explicit( |
||||
{0, 1024, 2048, 4096, 16384, 65536, 262144, 1048576, 4194304, 16777216, |
||||
67108864, 268435456, 1073741824, 4294967296})); |
||||
} |
||||
|
||||
Aggregation MillisDistributionAggregation() { |
||||
return Aggregation::Distribution(BucketBoundaries::Explicit( |
||||
{0, 0.01, 0.05, 0.1, 0.3, 0.6, 0.8, 1, 2, 3, 4, |
||||
5, 6, 8, 10, 13, 16, 20, 25, 30, 40, 50, |
||||
65, 80, 100, 130, 160, 200, 250, 300, 400, 500, 650, |
||||
800, 1000, 2000, 5000, 10000, 20000, 50000, 100000})); |
||||
} |
||||
|
||||
Aggregation CountDistributionAggregation() { |
||||
return Aggregation::Distribution(BucketBoundaries::Exponential(17, 1.0, 2.0)); |
||||
} |
||||
|
||||
ViewDescriptor MinuteDescriptor() { |
||||
auto descriptor = ViewDescriptor(); |
||||
SetAggregationWindow(AggregationWindow::Interval(absl::Minutes(1)), |
||||
&descriptor); |
||||
return descriptor; |
||||
} |
||||
|
||||
ViewDescriptor HourDescriptor() { |
||||
auto descriptor = ViewDescriptor(); |
||||
SetAggregationWindow(AggregationWindow::Interval(absl::Hours(1)), |
||||
&descriptor); |
||||
return descriptor; |
||||
} |
||||
|
||||
} // namespace
|
||||
|
||||
void RegisterOpenCensusViewsForExport() { |
||||
ClientSentMessagesPerRpcCumulative().RegisterForExport(); |
||||
ClientSentBytesPerRpcCumulative().RegisterForExport(); |
||||
ClientReceivedMessagesPerRpcCumulative().RegisterForExport(); |
||||
ClientReceivedBytesPerRpcCumulative().RegisterForExport(); |
||||
ClientRoundtripLatencyCumulative().RegisterForExport(); |
||||
ClientServerLatencyCumulative().RegisterForExport(); |
||||
|
||||
ServerSentMessagesPerRpcCumulative().RegisterForExport(); |
||||
ServerSentBytesPerRpcCumulative().RegisterForExport(); |
||||
ServerReceivedMessagesPerRpcCumulative().RegisterForExport(); |
||||
ServerReceivedBytesPerRpcCumulative().RegisterForExport(); |
||||
ServerServerLatencyCumulative().RegisterForExport(); |
||||
} |
||||
|
||||
// client cumulative
|
||||
const ViewDescriptor& ClientSentBytesPerRpcCumulative() { |
||||
const static ViewDescriptor descriptor = |
||||
ViewDescriptor() |
||||
.set_name("grpc.io/client/sent_bytes_per_rpc/cumulative") |
||||
.set_measure(kRpcClientSentBytesPerRpcMeasureName) |
||||
.set_aggregation(BytesDistributionAggregation()) |
||||
.add_column(ClientMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ClientReceivedBytesPerRpcCumulative() { |
||||
const static ViewDescriptor descriptor = |
||||
ViewDescriptor() |
||||
.set_name("grpc.io/client/received_bytes_per_rpc/cumulative") |
||||
.set_measure(kRpcClientReceivedBytesPerRpcMeasureName) |
||||
.set_aggregation(BytesDistributionAggregation()) |
||||
.add_column(ClientMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ClientRoundtripLatencyCumulative() { |
||||
const static ViewDescriptor descriptor = |
||||
ViewDescriptor() |
||||
.set_name("grpc.io/client/roundtrip_latency/cumulative") |
||||
.set_measure(kRpcClientRoundtripLatencyMeasureName) |
||||
.set_aggregation(MillisDistributionAggregation()) |
||||
.add_column(ClientMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ClientServerLatencyCumulative() { |
||||
const static ViewDescriptor descriptor = |
||||
ViewDescriptor() |
||||
.set_name("grpc.io/client/server_latency/cumulative") |
||||
.set_measure(kRpcClientServerLatencyMeasureName) |
||||
.set_aggregation(MillisDistributionAggregation()) |
||||
.add_column(ClientMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ClientCompletedRpcsCumulative() { |
||||
const static ViewDescriptor descriptor = |
||||
ViewDescriptor() |
||||
.set_name("grpc.io/client/completed_rpcs/cumulative") |
||||
.set_measure(kRpcClientRoundtripLatencyMeasureName) |
||||
.set_aggregation(Aggregation::Count()) |
||||
.add_column(ClientMethodTagKey()) |
||||
.add_column(ClientStatusTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ClientSentMessagesPerRpcCumulative() { |
||||
const static ViewDescriptor descriptor = |
||||
ViewDescriptor() |
||||
.set_name("grpc.io/client/received_messages_per_rpc/cumulative") |
||||
.set_measure(kRpcClientSentMessagesPerRpcMeasureName) |
||||
.set_aggregation(CountDistributionAggregation()) |
||||
.add_column(ClientMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ClientReceivedMessagesPerRpcCumulative() { |
||||
const static ViewDescriptor descriptor = |
||||
ViewDescriptor() |
||||
.set_name("grpc.io/client/sent_messages_per_rpc/cumulative") |
||||
.set_measure(kRpcClientReceivedMessagesPerRpcMeasureName) |
||||
.set_aggregation(CountDistributionAggregation()) |
||||
.add_column(ClientMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
// server cumulative
|
||||
const ViewDescriptor& ServerSentBytesPerRpcCumulative() { |
||||
const static ViewDescriptor descriptor = |
||||
ViewDescriptor() |
||||
.set_name("grpc.io/server/received_bytes_per_rpc/cumulative") |
||||
.set_measure(kRpcServerSentBytesPerRpcMeasureName) |
||||
.set_aggregation(BytesDistributionAggregation()) |
||||
.add_column(ServerMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ServerReceivedBytesPerRpcCumulative() { |
||||
const static ViewDescriptor descriptor = |
||||
ViewDescriptor() |
||||
.set_name("grpc.io/server/sent_bytes_per_rpc/cumulative") |
||||
.set_measure(kRpcServerReceivedBytesPerRpcMeasureName) |
||||
.set_aggregation(BytesDistributionAggregation()) |
||||
.add_column(ServerMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ServerServerLatencyCumulative() { |
||||
const static ViewDescriptor descriptor = |
||||
ViewDescriptor() |
||||
.set_name("grpc.io/server/elapsed_time/cumulative") |
||||
.set_measure(kRpcServerServerLatencyMeasureName) |
||||
.set_aggregation(MillisDistributionAggregation()) |
||||
.add_column(ServerMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ServerCompletedRpcsCumulative() { |
||||
const static ViewDescriptor descriptor = |
||||
ViewDescriptor() |
||||
.set_name("grpc.io/server/completed_rpcs/cumulative") |
||||
.set_measure(kRpcServerServerLatencyMeasureName) |
||||
.set_aggregation(Aggregation::Count()) |
||||
.add_column(ServerMethodTagKey()) |
||||
.add_column(ServerStatusTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ServerSentMessagesPerRpcCumulative() { |
||||
const static ViewDescriptor descriptor = |
||||
ViewDescriptor() |
||||
.set_name("grpc.io/server/received_messages_per_rpc/cumulative") |
||||
.set_measure(kRpcServerSentMessagesPerRpcMeasureName) |
||||
.set_aggregation(CountDistributionAggregation()) |
||||
.add_column(ServerMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ServerReceivedMessagesPerRpcCumulative() { |
||||
const static ViewDescriptor descriptor = |
||||
ViewDescriptor() |
||||
.set_name("grpc.io/server/sent_messages_per_rpc/cumulative") |
||||
.set_measure(kRpcServerReceivedMessagesPerRpcMeasureName) |
||||
.set_aggregation(CountDistributionAggregation()) |
||||
.add_column(ServerMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
// client minute
|
||||
const ViewDescriptor& ClientSentBytesPerRpcMinute() { |
||||
const static ViewDescriptor descriptor = |
||||
MinuteDescriptor() |
||||
.set_name("grpc.io/client/sent_bytes_per_rpc/minute") |
||||
.set_measure(kRpcClientSentBytesPerRpcMeasureName) |
||||
.set_aggregation(BytesDistributionAggregation()) |
||||
.add_column(ClientMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ClientReceivedBytesPerRpcMinute() { |
||||
const static ViewDescriptor descriptor = |
||||
MinuteDescriptor() |
||||
.set_name("grpc.io/client/received_bytes_per_rpc/minute") |
||||
.set_measure(kRpcClientReceivedBytesPerRpcMeasureName) |
||||
.set_aggregation(BytesDistributionAggregation()) |
||||
.add_column(ClientMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ClientRoundtripLatencyMinute() { |
||||
const static ViewDescriptor descriptor = |
||||
MinuteDescriptor() |
||||
.set_name("grpc.io/client/roundtrip_latency/minute") |
||||
.set_measure(kRpcClientRoundtripLatencyMeasureName) |
||||
.set_aggregation(MillisDistributionAggregation()) |
||||
.add_column(ClientMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ClientServerLatencyMinute() { |
||||
const static ViewDescriptor descriptor = |
||||
MinuteDescriptor() |
||||
.set_name("grpc.io/client/server_latency/minute") |
||||
.set_measure(kRpcClientServerLatencyMeasureName) |
||||
.set_aggregation(MillisDistributionAggregation()) |
||||
.add_column(ClientMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ClientCompletedRpcsMinute() { |
||||
const static ViewDescriptor descriptor = |
||||
MinuteDescriptor() |
||||
.set_name("grpc.io/client/completed_rpcs/minute") |
||||
.set_measure(kRpcClientRoundtripLatencyMeasureName) |
||||
.set_aggregation(Aggregation::Count()) |
||||
.add_column(ClientMethodTagKey()) |
||||
.add_column(ClientStatusTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ClientSentMessagesPerRpcMinute() { |
||||
const static ViewDescriptor descriptor = |
||||
MinuteDescriptor() |
||||
.set_name("grpc.io/client/sent_messages_per_rpc/minute") |
||||
.set_measure(kRpcClientSentMessagesPerRpcMeasureName) |
||||
.set_aggregation(CountDistributionAggregation()) |
||||
.add_column(ClientMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ClientReceivedMessagesPerRpcMinute() { |
||||
const static ViewDescriptor descriptor = |
||||
MinuteDescriptor() |
||||
.set_name("grpc.io/client/received_messages_per_rpc/minute") |
||||
.set_measure(kRpcClientReceivedMessagesPerRpcMeasureName) |
||||
.set_aggregation(CountDistributionAggregation()) |
||||
.add_column(ClientMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
// server minute
|
||||
const ViewDescriptor& ServerSentBytesPerRpcMinute() { |
||||
const static ViewDescriptor descriptor = |
||||
MinuteDescriptor() |
||||
.set_name("grpc.io/server/sent_bytes_per_rpc/minute") |
||||
.set_measure(kRpcServerSentBytesPerRpcMeasureName) |
||||
.set_aggregation(BytesDistributionAggregation()) |
||||
.add_column(ServerMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ServerReceivedBytesPerRpcMinute() { |
||||
const static ViewDescriptor descriptor = |
||||
MinuteDescriptor() |
||||
.set_name("grpc.io/server/received_bytes_per_rpc/minute") |
||||
.set_measure(kRpcServerReceivedBytesPerRpcMeasureName) |
||||
.set_aggregation(BytesDistributionAggregation()) |
||||
.add_column(ServerMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ServerServerLatencyMinute() { |
||||
const static ViewDescriptor descriptor = |
||||
MinuteDescriptor() |
||||
.set_name("grpc.io/server/server_latency/minute") |
||||
.set_measure(kRpcServerServerLatencyMeasureName) |
||||
.set_aggregation(MillisDistributionAggregation()) |
||||
.add_column(ServerMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ServerCompletedRpcsMinute() { |
||||
const static ViewDescriptor descriptor = |
||||
MinuteDescriptor() |
||||
.set_name("grpc.io/server/completed_rpcs/minute") |
||||
.set_measure(kRpcServerServerLatencyMeasureName) |
||||
.set_aggregation(Aggregation::Count()) |
||||
.add_column(ServerMethodTagKey()) |
||||
.add_column(ServerStatusTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ServerSentMessagesPerRpcMinute() { |
||||
const static ViewDescriptor descriptor = |
||||
MinuteDescriptor() |
||||
.set_name("grpc.io/server/sent_messages_per_rpc/minute") |
||||
.set_measure(kRpcServerSentMessagesPerRpcMeasureName) |
||||
.set_aggregation(CountDistributionAggregation()) |
||||
.add_column(ServerMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ServerReceivedMessagesPerRpcMinute() { |
||||
const static ViewDescriptor descriptor = |
||||
MinuteDescriptor() |
||||
.set_name("grpc.io/server/received_messages_per_rpc/minute") |
||||
.set_measure(kRpcServerReceivedMessagesPerRpcMeasureName) |
||||
.set_aggregation(CountDistributionAggregation()) |
||||
.add_column(ServerMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
// client hour
|
||||
const ViewDescriptor& ClientSentBytesPerRpcHour() { |
||||
const static ViewDescriptor descriptor = |
||||
HourDescriptor() |
||||
.set_name("grpc.io/client/sent_bytes_per_rpc/hour") |
||||
.set_measure(kRpcClientSentBytesPerRpcMeasureName) |
||||
.set_aggregation(BytesDistributionAggregation()) |
||||
.add_column(ClientMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ClientReceivedBytesPerRpcHour() { |
||||
const static ViewDescriptor descriptor = |
||||
HourDescriptor() |
||||
.set_name("grpc.io/client/received_bytes_per_rpc/hour") |
||||
.set_measure(kRpcClientReceivedBytesPerRpcMeasureName) |
||||
.set_aggregation(BytesDistributionAggregation()) |
||||
.add_column(ClientMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ClientRoundtripLatencyHour() { |
||||
const static ViewDescriptor descriptor = |
||||
HourDescriptor() |
||||
.set_name("grpc.io/client/roundtrip_latency/hour") |
||||
.set_measure(kRpcClientRoundtripLatencyMeasureName) |
||||
.set_aggregation(MillisDistributionAggregation()) |
||||
.add_column(ClientMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ClientServerLatencyHour() { |
||||
const static ViewDescriptor descriptor = |
||||
HourDescriptor() |
||||
.set_name("grpc.io/client/server_latency/hour") |
||||
.set_measure(kRpcClientServerLatencyMeasureName) |
||||
.set_aggregation(MillisDistributionAggregation()) |
||||
.add_column(ClientMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ClientCompletedRpcsHour() { |
||||
const static ViewDescriptor descriptor = |
||||
HourDescriptor() |
||||
.set_name("grpc.io/client/completed_rpcs/hour") |
||||
.set_measure(kRpcClientRoundtripLatencyMeasureName) |
||||
.set_aggregation(Aggregation::Count()) |
||||
.add_column(ClientMethodTagKey()) |
||||
.add_column(ClientStatusTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ClientSentMessagesPerRpcHour() { |
||||
const static ViewDescriptor descriptor = |
||||
HourDescriptor() |
||||
.set_name("grpc.io/client/sent_messages_per_rpc/hour") |
||||
.set_measure(kRpcClientSentMessagesPerRpcMeasureName) |
||||
.set_aggregation(CountDistributionAggregation()) |
||||
.add_column(ClientMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ClientReceivedMessagesPerRpcHour() { |
||||
const static ViewDescriptor descriptor = |
||||
HourDescriptor() |
||||
.set_name("grpc.io/client/received_messages_per_rpc/hour") |
||||
.set_measure(kRpcClientReceivedMessagesPerRpcMeasureName) |
||||
.set_aggregation(CountDistributionAggregation()) |
||||
.add_column(ClientMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
// server hour
|
||||
const ViewDescriptor& ServerSentBytesPerRpcHour() { |
||||
const static ViewDescriptor descriptor = |
||||
HourDescriptor() |
||||
.set_name("grpc.io/server/sent_bytes_per_rpc/hour") |
||||
.set_measure(kRpcServerSentBytesPerRpcMeasureName) |
||||
.set_aggregation(BytesDistributionAggregation()) |
||||
.add_column(ServerMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ServerReceivedBytesPerRpcHour() { |
||||
const static ViewDescriptor descriptor = |
||||
HourDescriptor() |
||||
.set_name("grpc.io/server/received_bytes_per_rpc/hour") |
||||
.set_measure(kRpcServerReceivedBytesPerRpcMeasureName) |
||||
.set_aggregation(BytesDistributionAggregation()) |
||||
.add_column(ServerMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ServerServerLatencyHour() { |
||||
const static ViewDescriptor descriptor = |
||||
HourDescriptor() |
||||
.set_name("grpc.io/server/server_latency/hour") |
||||
.set_measure(kRpcServerServerLatencyMeasureName) |
||||
.set_aggregation(MillisDistributionAggregation()) |
||||
.add_column(ServerMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ServerCompletedRpcsHour() { |
||||
const static ViewDescriptor descriptor = |
||||
HourDescriptor() |
||||
.set_name("grpc.io/server/completed_rpcs/hour") |
||||
.set_measure(kRpcServerServerLatencyMeasureName) |
||||
.set_aggregation(Aggregation::Count()) |
||||
.add_column(ServerMethodTagKey()) |
||||
.add_column(ServerStatusTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ServerSentMessagesPerRpcHour() { |
||||
const static ViewDescriptor descriptor = |
||||
HourDescriptor() |
||||
.set_name("grpc.io/server/sent_messages_per_rpc/hour") |
||||
.set_measure(kRpcServerSentMessagesPerRpcMeasureName) |
||||
.set_aggregation(CountDistributionAggregation()) |
||||
.add_column(ServerMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
const ViewDescriptor& ServerReceivedMessagesPerRpcHour() { |
||||
const static ViewDescriptor descriptor = |
||||
HourDescriptor() |
||||
.set_name("grpc.io/server/received_messages_per_rpc/hour") |
||||
.set_measure(kRpcServerReceivedMessagesPerRpcMeasureName) |
||||
.set_aggregation(CountDistributionAggregation()) |
||||
.add_column(ServerMethodTagKey()); |
||||
return descriptor; |
||||
} |
||||
|
||||
} // namespace grpc
|
@ -1,3 +0,0 @@ |
||||
google.census.Tag.key max_size:255 |
||||
google.census.Tag.value max_size:255 |
||||
google.census.View.tag_key max_count:15 |
@ -1,307 +0,0 @@ |
||||
// Copyright 2016 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 google.census; |
||||
|
||||
// All the census protos. |
||||
// |
||||
// Nomenclature note: capitalized names below (like Resource) are protos. |
||||
// |
||||
// Census lets you define a Resource - something which can be measured, like the |
||||
// latency of an RPC, the number of CPU cycles spent on an operation, or |
||||
// anything else you care to measure. You can record individual instances of |
||||
// measurements (a double value) for every Resource of interest. These |
||||
// individual measurements are aggregated together into an Aggregation. There |
||||
// are two Aggregation types available: Distribution (describes the |
||||
// distribution of all measurements, possibly with a histogram) and |
||||
// IntervalStats (the count and mean of measurements across specified time |
||||
// periods). An Aggregation is described by an AggregationDescriptor. |
||||
// |
||||
// You can define how your stats are broken down by Tag values and which |
||||
// Aggregations to use through a View. The corresponding combination of |
||||
// Resource/View/Aggregation which is available to census clients is called a |
||||
// Metric. |
||||
|
||||
|
||||
// The following two types are copied from |
||||
// google/protobuf/{duration,timestamp}.proto. Ideally, we would be able to |
||||
// import them, but this causes compilation issues on C-based systems |
||||
// (e.g. https://koti.kapsi.fi/jpa/nanopb/), which cannot process the C++ |
||||
// headers generated from the standard protobuf distribution. See the relevant |
||||
// proto files for full documentation of these types. |
||||
|
||||
message Duration { |
||||
// Signed seconds of the span of time. Must be from -315,576,000,000 |
||||
// to +315,576,000,000 inclusive. |
||||
int64 seconds = 1; |
||||
|
||||
// Signed fractions of a second at nanosecond resolution of the span |
||||
// of time. Durations less than one second are represented with a 0 |
||||
// `seconds` field and a positive or negative `nanos` field. For durations |
||||
// of one second or more, a non-zero value for the `nanos` field must be |
||||
// of the same sign as the `seconds` field. Must be from -999,999,999 |
||||
// to +999,999,999 inclusive. |
||||
int32 nanos = 2; |
||||
} |
||||
|
||||
message Timestamp { |
||||
// Represents seconds of UTC time since Unix epoch |
||||
// 1970-01-01T00:00:00Z. Must be from from 0001-01-01T00:00:00Z to |
||||
// 9999-12-31T23:59:59Z inclusive. |
||||
int64 seconds = 1; |
||||
|
||||
// Non-negative fractions of a second at nanosecond resolution. Negative |
||||
// second values with fractions must still have non-negative nanos values |
||||
// that count forward in time. Must be from 0 to 999,999,999 |
||||
// inclusive. |
||||
int32 nanos = 2; |
||||
} |
||||
|
||||
// Describes a Resource. |
||||
message Resource { |
||||
// name of resource, e.g. rpc_latency, cpu. Must be unique. |
||||
string name = 1; |
||||
|
||||
// More detailed description of the resource, used in documentation. |
||||
string description = 2; |
||||
|
||||
// Fundamental units of measurement supported by Census |
||||
// TODO(aveitch): expand this to include other S.I. units? |
||||
enum BasicUnit { |
||||
UNKNOWN = 0; |
||||
BITS = 1; |
||||
BYTES = 2; |
||||
SECS = 3; |
||||
CORES = 4; |
||||
MAX_UNITS = 5; |
||||
} |
||||
|
||||
// MeasurementUnit lets you build compound units of the form |
||||
// 10^n * (A * B * ...) / (X * Y * ...), |
||||
// where the elements in the numerator and denominator are all BasicUnits. A |
||||
// MeasurementUnit must have at least one BasicUnit in its numerator. |
||||
// |
||||
// To specify multiplication in the numerator or denominator, simply specify |
||||
// multiple numerator or denominator fields. For example: |
||||
// |
||||
// - byte-seconds (i.e. bytes * seconds): |
||||
// numerator: BYTES |
||||
// numerator: SECS |
||||
// |
||||
// - events/sec^2 (i.e. rate of change of events/sec): |
||||
// numerator: COUNT |
||||
// denominator: SECS |
||||
// denominator: SECS |
||||
// |
||||
// To specify multiples (in power of 10) of units, specify a non-zero prefix |
||||
// value, for example: |
||||
// |
||||
// - MB/s (i.e. megabytes / s): |
||||
// prefix: 6 |
||||
// numerator: BYTES |
||||
// denominator: SECS |
||||
// |
||||
// - nanoseconds |
||||
// prefix: -9 |
||||
// numerator: SECS |
||||
message MeasurementUnit { |
||||
int32 prefix = 1; |
||||
repeated BasicUnit numerator = 2; |
||||
repeated BasicUnit denominator = 3; |
||||
} |
||||
|
||||
// The units in which Resource values are measured. |
||||
MeasurementUnit unit = 3; |
||||
} |
||||
|
||||
// An Aggregation summarizes a series of individual Resource measurements, an |
||||
// AggregationDescriptor describes an Aggregation. |
||||
message AggregationDescriptor { |
||||
enum AggregationType { |
||||
// Unspecified. Should not be used. |
||||
UNKNOWN = 0; |
||||
// A count of measurements made. |
||||
COUNT = 1; |
||||
// A Distribution. |
||||
DISTRIBUTION = 2; |
||||
// Counts over fixed time intervals. |
||||
INTERVAL = 3; |
||||
} |
||||
// The type of Aggregation. |
||||
AggregationType type = 1; |
||||
|
||||
// At most one set of options. It is illegal to specifiy an option for |
||||
// COUNT Aggregations. interval_boundaries must be set for INTERVAL types. |
||||
// bucket_boundaries are optional for DISTRIBUTION types. |
||||
oneof options { |
||||
// Defines histogram bucket boundaries for Distributions. |
||||
BucketBoundaries bucket_boundaries = 2; |
||||
// Defines the time windows to record for IntervalStats. |
||||
IntervalBoundaries interval_boundaries = 3; |
||||
} |
||||
|
||||
// A Distribution may optionally contain a histogram of the values in the |
||||
// population. The bucket boundaries for that histogram are described by |
||||
// `bucket_boundaries`. This defines `size(bounds) + 1` (= N) buckets. The |
||||
// boundaries for bucket index i are: |
||||
// |
||||
// [-infinity, bounds[i]) for i == 0 |
||||
// [bounds[i-1], bounds[i]) for 0 < i < N-2 |
||||
// [bounds[i-1], +infinity) for i == N-1 |
||||
// |
||||
// i.e. an underflow bucket (number 0), zero or more finite buckets (1 |
||||
// through N - 2, and an overflow bucket (N - 1), with inclusive lower |
||||
// bounds and exclusive upper bounds. |
||||
// |
||||
// There must be at least one element in `bounds`. If `bounds` has only one |
||||
// element, there are no finite buckets, and that single element is the |
||||
// common boundary of the overflow and underflow buckets. |
||||
message BucketBoundaries { |
||||
// The values must be monotonically increasing. |
||||
repeated double bounds = 1; |
||||
} |
||||
|
||||
// For Interval stats, describe the size of each window. |
||||
message IntervalBoundaries { |
||||
// For each time window, specify a duration in seconds. |
||||
repeated double window_size = 1; |
||||
} |
||||
} |
||||
|
||||
// Distribution contains summary statistics for a population of values and, |
||||
// optionally, a histogram representing the distribution of those values across |
||||
// a specified set of histogram buckets, as defined in |
||||
// Aggregation.bucket_options. |
||||
// |
||||
// The summary statistics are the count, mean, minimum, and the maximum of the |
||||
// set of population of values. |
||||
// |
||||
// Although it is not forbidden, it is generally a bad idea to include |
||||
// non-finite values (infinities or NaNs) in the population of values, as this |
||||
// will render the `mean` field meaningless. |
||||
message Distribution { |
||||
// The number of values in the population. Must be non-negative. |
||||
int64 count = 1; |
||||
|
||||
// The arithmetic mean of the values in the population. If `count` is zero |
||||
// then this field must be zero. |
||||
double mean = 2; |
||||
|
||||
// Describes a range of population values. |
||||
message Range { |
||||
// The minimum of the population values. |
||||
double min = 1; |
||||
// The maximum of the population values. |
||||
double max = 2; |
||||
} |
||||
|
||||
// The range of the population values. If `count` is zero, this field will not |
||||
// be defined. |
||||
Range range = 3; |
||||
|
||||
// A Distribution may optionally contain a histogram of the values in the |
||||
// population. The histogram is given in `bucket_count` as counts of values |
||||
// that fall into one of a sequence of non-overlapping buckets, as described |
||||
// by `AggregationDescriptor.options.bucket_boundaries`. |
||||
// The sum of the values in `bucket_counts` must equal the value in `count`. |
||||
// |
||||
// Bucket counts are given in order under the numbering scheme described |
||||
// above (the underflow bucket has number 0; the finite buckets, if any, |
||||
// have numbers 1 through N-2; the overflow bucket has number N-1). |
||||
// |
||||
// The size of `bucket_count` must be no greater than N as defined in |
||||
// `bucket_boundaries`. |
||||
// |
||||
// Any suffix of trailing zero bucket_count fields may be omitted. |
||||
repeated int64 bucket_count = 4; |
||||
} |
||||
|
||||
// Record summary stats over various time windows. |
||||
message IntervalStats { |
||||
// Summary statistic over a single time window. |
||||
message Window { |
||||
// The window duration. Must be positive. |
||||
Duration window_size = 1; |
||||
// The number of measurements in this window. |
||||
int64 count = 2; |
||||
// The arithmetic mean of all measurements in the window. |
||||
double mean = 3; |
||||
} |
||||
|
||||
// Full set of windows for this aggregation. |
||||
repeated Window window = 1; |
||||
} |
||||
|
||||
// A Tag: key-value pair. |
||||
message Tag { |
||||
string key = 1; |
||||
string value = 2; |
||||
} |
||||
|
||||
// A View specifies an Aggregation and a set of tag keys. The Aggregation will |
||||
// be broken down by the unique set of matching tag values for each measurement. |
||||
message View { |
||||
// Name of view. Must be unique. |
||||
string name = 1; |
||||
|
||||
// More detailed description, for documentation purposes. |
||||
string description = 2; |
||||
|
||||
// Name of Resource to be broken down for this view. |
||||
string resource_name = 3; |
||||
|
||||
// Aggregation type to associate with this View. |
||||
AggregationDescriptor aggregation = 4; |
||||
|
||||
// Tag keys to match with a given Resource measurement. If no keys are |
||||
// specified, then all stats are recorded. Keys must be unique. |
||||
repeated string tag_key = 5; |
||||
} |
||||
|
||||
// An Aggregation summarizes a series of individual Resource measurements. |
||||
message Aggregation { |
||||
// Name of this aggregation. |
||||
string name = 1; |
||||
|
||||
// More detailed description, for documentation purposes. |
||||
string description = 2; |
||||
|
||||
// The data for this Aggregation. |
||||
oneof data { |
||||
uint64 count = 3; |
||||
Distribution distribution = 4; |
||||
IntervalStats interval_stats = 5; |
||||
} |
||||
|
||||
// Tags associated with this Aggregation. |
||||
repeated Tag tag = 6; |
||||
} |
||||
|
||||
// A Metric represents all the Aggregations for a particular view. |
||||
message Metric { |
||||
// View associated with this Metric. |
||||
string view_name = 1; |
||||
|
||||
// Aggregations - each will have a unique set of tag values for the tag_keys |
||||
// associated with the corresponding View. |
||||
repeated Aggregation aggregation = 2; |
||||
|
||||
// Start and end timestamps over which the metric was accumulated. These |
||||
// values are not relevant/defined for IntervalStats aggregations, which are |
||||
// always accumulated over a fixed time period. |
||||
Timestamp start = 3; |
||||
Timestamp end = 4; |
||||
} |
@ -1,29 +0,0 @@ |
||||
// Copyright 2016 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 google.trace; |
||||
|
||||
// Tracing information that is propagated with RPC's. |
||||
message TraceContext { |
||||
// A TraceId uniquely represents a single Trace. It is a 128-bit nonce. |
||||
// The 128-bit ID is split into 2 64-bit chunks. (REQUIRED) |
||||
fixed64 trace_id_hi = 1; |
||||
fixed64 trace_id_lo = 2; |
||||
// ID of parent (client) span. (REQUIRED) |
||||
fixed64 span_id = 3; |
||||
// Span option flags. First bit is true if this trace is sampled. (OPTIONAL) |
||||
fixed32 span_options = 4; |
||||
} |
@ -0,0 +1,54 @@ |
||||
# 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. |
||||
|
||||
require 'open3' |
||||
require 'tmpdir' |
||||
|
||||
def main |
||||
root_dir = File.join(File.dirname(__FILE__), '..', '..', '..') |
||||
pb_dir = File.join(root_dir, 'src', 'ruby', 'end2end', 'protos') |
||||
|
||||
fail 'CONFIG env variable unexpectedly unset' unless ENV['CONFIG'] |
||||
bins_sub_dir = ENV['CONFIG'] |
||||
bins_dir = File.join(root_dir, 'bins', bins_sub_dir) |
||||
|
||||
plugin = File.join(bins_dir, 'grpc_ruby_plugin') |
||||
protoc = File.join(bins_dir, 'protobuf', 'protoc') |
||||
|
||||
got = nil |
||||
|
||||
Dir.mktmpdir do |tmp_dir| |
||||
gen_out = File.join(tmp_dir, 'package_with_underscore', 'service_services_pb.rb') |
||||
|
||||
pid = spawn( |
||||
protoc, |
||||
"--proto_path=#{pb_dir}", |
||||
'package_with_underscore/service.proto', |
||||
"--grpc_out=#{tmp_dir}", |
||||
"--plugin=protoc-gen-grpc=#{plugin}" |
||||
) |
||||
Process.waitpid2(pid) |
||||
File.open(gen_out) { |f| got = f.read } |
||||
end |
||||
|
||||
correct_modularized_rpc = 'rpc :TestOne, ' \ |
||||
'Grpc::Testing::PackageWithUnderscore::Data::Request, ' \ |
||||
'Grpc::Testing::PackageWithUnderscore::Data::Response' |
||||
|
||||
return if got.include?(correct_modularized_rpc) |
||||
|
||||
fail 'generated file does not match with correct_modularized_rpc' |
||||
end |
||||
|
||||
main |
@ -1,51 +0,0 @@ |
||||
# Copyright 2016 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. |
||||
|
||||
require 'open3' |
||||
require 'tmpdir' |
||||
|
||||
describe 'Package with underscore protobuf code generation' do |
||||
it 'should have the same content as created by code generation' do |
||||
root_dir = File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..') |
||||
pb_dir = File.join(root_dir, 'src', 'ruby', 'spec', 'pb') |
||||
|
||||
fail 'CONFIG env variable unexpectedly unset' unless ENV['CONFIG'] |
||||
bins_sub_dir = ENV['CONFIG'] |
||||
bins_dir = File.join(root_dir, 'bins', bins_sub_dir) |
||||
|
||||
plugin = File.join(bins_dir, 'grpc_ruby_plugin') |
||||
protoc = File.join(bins_dir, 'protobuf', 'protoc') |
||||
|
||||
got = nil |
||||
|
||||
Dir.mktmpdir do |tmp_dir| |
||||
gen_out = File.join(tmp_dir, 'package_with_underscore', 'service_services_pb.rb') |
||||
|
||||
pid = spawn( |
||||
protoc, |
||||
'-I.', |
||||
'package_with_underscore/service.proto', |
||||
"--grpc_out=#{tmp_dir}", |
||||
"--plugin=protoc-gen-grpc=#{plugin}", |
||||
chdir: pb_dir) |
||||
Process.waitpid2(pid) |
||||
File.open(gen_out) { |f| got = f.read } |
||||
end |
||||
|
||||
correct_modularized_rpc = 'rpc :TestOne, ' \ |
||||
'Grpc::Testing::PackageWithUnderscore::Data::Request, ' \ |
||||
'Grpc::Testing::PackageWithUnderscore::Data::Response' |
||||
expect(got).to include(correct_modularized_rpc) |
||||
end |
||||
end |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue