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