470 lines
21 KiB
C
470 lines
21 KiB
C
/*
|
|
*
|
|
* Copyright 2015-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.
|
|
*
|
|
*/
|
|
|
|
/** RPC-internal Census API's. These are designed to be generic enough that
|
|
* they can (ultimately) be used in many different RPC systems (with differing
|
|
* implementations). */
|
|
|
|
#ifndef GRPC_CENSUS_H
|
|
#define GRPC_CENSUS_H
|
|
|
|
#include <grpc/grpc.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/** Identify census features that can be enabled via census_initialize(). */
|
|
enum census_features {
|
|
CENSUS_FEATURE_NONE = 0, /** Do not enable census. */
|
|
CENSUS_FEATURE_TRACING = 1, /** Enable census tracing. */
|
|
CENSUS_FEATURE_STATS = 2, /** Enable Census stats collection. */
|
|
CENSUS_FEATURE_CPU = 4, /** Enable Census CPU usage collection. */
|
|
CENSUS_FEATURE_ALL =
|
|
CENSUS_FEATURE_TRACING | CENSUS_FEATURE_STATS | CENSUS_FEATURE_CPU
|
|
};
|
|
|
|
/** Shutdown and startup census subsystem. The 'features' argument should be
|
|
* the OR (|) of census_features values. If census fails to initialize, then
|
|
* census_initialize() will return -1, otherwise the set of enabled features
|
|
* (which may be smaller than that provided in the `features` argument, see
|
|
* census_supported()) is returned. It is an error to call census_initialize()
|
|
* more than once (without an intervening census_shutdown()). These functions
|
|
* are not thread-safe. */
|
|
CENSUSAPI int census_initialize(int features);
|
|
CENSUSAPI void census_shutdown(void);
|
|
|
|
/** Return the features supported by the current census implementation (not all
|
|
* features will be available on all platforms). */
|
|
CENSUSAPI int census_supported(void);
|
|
|
|
/** Return the census features currently enabled. */
|
|
CENSUSAPI int census_enabled(void);
|
|
|
|
/**
|
|
A Census Context is a handle used by Census to represent the current tracing
|
|
and stats collection information. Contexts should be propagated across RPC's
|
|
(this is the responsibility of the local RPC system). A context is typically
|
|
used as the first argument to most census functions. Conceptually, they
|
|
should be thought of as specific to a single RPC/thread. The user visible
|
|
context representation is that of a collection of key:value string pairs,
|
|
each of which is termed a 'tag'; these form the basis against which Census
|
|
metrics will be recorded. Keys are unique within a context. */
|
|
typedef struct census_context census_context;
|
|
|
|
/** A tag is a key:value pair. Both keys and values are nil-terminated strings,
|
|
containing printable ASCII characters (decimal 32-126). Keys must be at
|
|
least one character in length. Both keys and values can have at most
|
|
CENSUS_MAX_TAG_KB_LEN characters (including the terminating nil). The
|
|
maximum number of tags that can be propagated is
|
|
CENSUS_MAX_PROPAGATED_TAGS. Users should also remember that some systems
|
|
may have limits on, e.g., the number of bytes that can be transmitted as
|
|
metadata, and that larger tags means more memory consumed and time in
|
|
processing. */
|
|
typedef struct {
|
|
const char *key;
|
|
const char *value;
|
|
uint8_t flags;
|
|
} census_tag;
|
|
|
|
/** Maximum length of a tag's key or value. */
|
|
#define CENSUS_MAX_TAG_KV_LEN 255
|
|
/** Maximum number of propagatable tags. */
|
|
#define CENSUS_MAX_PROPAGATED_TAGS 255
|
|
|
|
/** Tag flags. */
|
|
#define CENSUS_TAG_PROPAGATE 1 /** Tag should be propagated over RPC */
|
|
#define CENSUS_TAG_STATS 2 /** Tag will be used for statistics aggregation */
|
|
#define CENSUS_TAG_RESERVED 4 /** Reserved for internal use. */
|
|
/** Flag values 4,8,16,32,64,128 are reserved for future/internal use. Clients
|
|
should not use or rely on their values. */
|
|
|
|
#define CENSUS_TAG_IS_PROPAGATED(flags) (flags & CENSUS_TAG_PROPAGATE)
|
|
#define CENSUS_TAG_IS_STATS(flags) (flags & CENSUS_TAG_STATS)
|
|
|
|
/** An instance of this structure is kept by every context, and records the
|
|
basic information associated with the creation of that context. */
|
|
typedef struct {
|
|
int n_propagated_tags; /** number of propagated tags */
|
|
int n_local_tags; /** number of non-propagated (local) tags */
|
|
int n_deleted_tags; /** number of tags that were deleted */
|
|
int n_added_tags; /** number of tags that were added */
|
|
int n_modified_tags; /** number of tags that were modified */
|
|
int n_invalid_tags; /** number of tags with bad keys or values (e.g.
|
|
longer than CENSUS_MAX_TAG_KV_LEN) */
|
|
int n_ignored_tags; /** number of tags ignored because of
|
|
CENSUS_MAX_PROPAGATED_TAGS limit. */
|
|
} census_context_status;
|
|
|
|
/** Create a new context, adding and removing tags from an existing context.
|
|
This will copy all tags from the 'tags' input, so it is recommended
|
|
to add as many tags in a single operation as is practical for the client.
|
|
@param base Base context to build upon. Can be NULL.
|
|
@param tags A set of tags to be added/changed/deleted. Tags with keys that
|
|
are in 'tags', but not 'base', are added to the context. Keys that are in
|
|
both 'tags' and 'base' will have their value/flags modified. Tags with keys
|
|
in both, but with NULL values, will be deleted from the context. Tags with
|
|
invalid (too long or short) keys or values will be ignored.
|
|
If adding a tag will result in more than CENSUS_MAX_PROPAGATED_TAGS in either
|
|
binary or non-binary tags, they will be ignored, as will deletions of
|
|
tags that don't exist.
|
|
@param ntags number of tags in 'tags'
|
|
@param status If not NULL, will return a pointer to a census_context_status
|
|
structure containing information about the new context and status of the
|
|
tags used in its creation.
|
|
@return A new, valid census_context.
|
|
*/
|
|
CENSUSAPI census_context *census_context_create(
|
|
const census_context *base, const census_tag *tags, int ntags,
|
|
census_context_status const **status);
|
|
|
|
/** Destroy a context. Once this function has been called, the context cannot
|
|
be reused. */
|
|
CENSUSAPI void census_context_destroy(census_context *context);
|
|
|
|
/** Get a pointer to the original status from the context creation. */
|
|
CENSUSAPI const census_context_status *census_context_get_status(
|
|
const census_context *context);
|
|
|
|
/** Structure used for iterating over the tags in a context. API clients should
|
|
not use or reference internal fields - neither their contents or
|
|
presence/absence are guaranteed. */
|
|
typedef struct {
|
|
const census_context *context;
|
|
int base;
|
|
int index;
|
|
char *kvm;
|
|
} census_context_iterator;
|
|
|
|
/** Initialize a census_tag_iterator. Must be called before first use. */
|
|
CENSUSAPI void census_context_initialize_iterator(
|
|
const census_context *context, census_context_iterator *iterator);
|
|
|
|
/** Get the contents of the "next" tag in the context. If there are no more
|
|
tags, returns 0 (and 'tag' contents will be unchanged), otherwise returns 1.
|
|
*/
|
|
CENSUSAPI int census_context_next_tag(census_context_iterator *iterator,
|
|
census_tag *tag);
|
|
|
|
/** Get a context tag by key. Returns 0 if the key is not present. */
|
|
CENSUSAPI int census_context_get_tag(const census_context *context,
|
|
const char *key, census_tag *tag);
|
|
|
|
/** Tag set encode/decode functionality. These functions are intended
|
|
for use by RPC systems only, for purposes of transmitting/receiving contexts.
|
|
*/
|
|
|
|
/** Encode a context into a buffer.
|
|
@param context context to be encoded
|
|
@param buffer buffer into which the context will be encoded.
|
|
@param buf_size number of available bytes in buffer.
|
|
@return The number of buffer bytes consumed for the encoded context, or
|
|
zero if the buffer was of insufficient size. */
|
|
CENSUSAPI size_t census_context_encode(const census_context *context,
|
|
char *buffer, size_t buf_size);
|
|
|
|
/** Decode context buffer encoded with census_context_encode(). Returns NULL
|
|
if there is an error in parsing either buffer. */
|
|
CENSUSAPI census_context *census_context_decode(const char *buffer,
|
|
size_t size);
|
|
|
|
/** Distributed traces can have a number of options. */
|
|
enum census_trace_mask_values {
|
|
CENSUS_TRACE_MASK_NONE = 0, /** Default, empty flags */
|
|
CENSUS_TRACE_MASK_IS_SAMPLED = 1 /** RPC tracing enabled for this context. */
|
|
};
|
|
|
|
/** Get the current trace mask associated with this context. The value returned
|
|
will be the logical OR of census_trace_mask_values values. */
|
|
CENSUSAPI int census_trace_mask(const census_context *context);
|
|
|
|
/** Set the trace mask associated with a context. */
|
|
CENSUSAPI void census_set_trace_mask(int trace_mask);
|
|
|
|
/** The concept of "operation" is a fundamental concept for Census. In an RPC
|
|
system, an operation typically represents a single RPC, or a significant
|
|
sub-part thereof (e.g. a single logical "read" RPC to a distributed storage
|
|
system might do several other actions in parallel, from looking up metadata
|
|
indices to making requests of other services - each of these could be a
|
|
sub-operation with the larger RPC operation). Census uses operations for the
|
|
following:
|
|
|
|
CPU accounting: If enabled, census will measure the thread CPU time
|
|
consumed between operation start and end times.
|
|
|
|
Active operations: Census will maintain information on all currently
|
|
active operations.
|
|
|
|
Distributed tracing: Each operation serves as a logical trace span.
|
|
|
|
Stats collection: Stats are broken down by operation (e.g. latency
|
|
breakdown for each unique RPC path).
|
|
|
|
The following functions serve to delineate the start and stop points for
|
|
each logical operation. */
|
|
|
|
/**
|
|
This structure represents a timestamp as used by census to record the time
|
|
at which an operation begins.
|
|
*/
|
|
typedef struct {
|
|
/** Use gpr_timespec for default implementation. High performance
|
|
* implementations should use a cycle-counter based timestamp. */
|
|
gpr_timespec ts;
|
|
} census_timestamp;
|
|
|
|
/**
|
|
Mark the beginning of an RPC operation. The information required to call the
|
|
functions to record the start of RPC operations (both client and server) may
|
|
not be callable at the true start time of the operation, due to information
|
|
not being available (e.g. the census context data will not be available in a
|
|
server RPC until at least initial metadata has been processed). To ensure
|
|
correct CPU accounting and latency recording, RPC systems can call this
|
|
function to get the timestamp of operation beginning. This can later be used
|
|
as an argument to census_start_{client,server}_rpc_op(). NB: for correct
|
|
CPU accounting, the system must guarantee that the same thread is used
|
|
for all request processing after this function is called.
|
|
|
|
@return A timestamp representing the operation start time.
|
|
*/
|
|
CENSUSAPI census_timestamp census_start_rpc_op_timestamp(void);
|
|
|
|
/**
|
|
Represent functions to map RPC name ID to service/method names. Census
|
|
breaks down all RPC stats by service and method names. We leave the
|
|
definition and format of these to the RPC system. For efficiency purposes,
|
|
we encode these as a single 64 bit identifier, and allow the RPC system to
|
|
provide a structure for functions that can convert these to service and
|
|
method strings.
|
|
|
|
TODO(aveitch): Instead of providing this as an argument to the rpc_start_op()
|
|
functions, maybe it should be set once at census initialization.
|
|
*/
|
|
typedef struct {
|
|
const char *(*get_rpc_service_name)(int64_t id);
|
|
const char *(*get_rpc_method_name)(int64_t id);
|
|
} census_rpc_name_info;
|
|
|
|
/**
|
|
Start a client rpc operation. This function should be called as early in the
|
|
client RPC path as possible. This function will create a new context. If
|
|
the context argument is non-null, then the new context will inherit all
|
|
its properties, with the following changes:
|
|
- create a new operation ID for the new context, marking it as a child of
|
|
the previous operation.
|
|
- use the new RPC path and peer information for tracing and stats
|
|
collection purposes, rather than those from the original context
|
|
|
|
If the context argument is NULL, then a new root context is created. This
|
|
is particularly important for tracing purposes (the trace spans generated
|
|
will be unassociated with any other trace spans, except those
|
|
downstream). The trace_mask will be used for tracing operations associated
|
|
with the new context.
|
|
|
|
In some RPC systems (e.g. where load balancing is used), peer information
|
|
may not be available at the time the operation starts. In this case, use a
|
|
NULL value for peer, and set it later using the
|
|
census_set_rpc_client_peer() function.
|
|
|
|
@param context The parent context. Can be NULL.
|
|
@param rpc_name_id The rpc name identifier to be associated with this RPC.
|
|
@param rpc_name_info Used to decode rpc_name_id.
|
|
@param peer RPC peer. If not available at the time, NULL can be used,
|
|
and a later census_set_rpc_client_peer() call made.
|
|
@param trace_mask An OR of census_trace_mask_values values. Only used in
|
|
the creation of a new root context (context == NULL).
|
|
@param start_time A timestamp returned from census_start_rpc_op_timestamp().
|
|
Can be NULL. Used to set the true time the operation
|
|
begins.
|
|
|
|
@return A new census context.
|
|
*/
|
|
CENSUSAPI census_context *census_start_client_rpc_op(
|
|
const census_context *context, int64_t rpc_name_id,
|
|
const census_rpc_name_info *rpc_name_info, const char *peer, int trace_mask,
|
|
const census_timestamp *start_time);
|
|
|
|
/**
|
|
Add peer information to a context representing a client RPC operation.
|
|
*/
|
|
CENSUSAPI void census_set_rpc_client_peer(census_context *context,
|
|
const char *peer);
|
|
|
|
/**
|
|
Start a server RPC operation. Returns a new context to be used in future
|
|
census calls. If buffer is non-NULL, then the buffer contents should
|
|
represent the client context, as generated by census_context_serialize().
|
|
If buffer is NULL, a new root context is created.
|
|
|
|
@param buffer Buffer containing bytes output from census_context_serialize().
|
|
@param rpc_name_id The rpc name identifier to be associated with this RPC.
|
|
@param rpc_name_info Used to decode rpc_name_id.
|
|
@param peer RPC peer.
|
|
@param trace_mask An OR of census_trace_mask_values values. Only used in
|
|
the creation of a new root context (buffer == NULL).
|
|
@param start_time A timestamp returned from census_start_rpc_op_timestamp().
|
|
Can be NULL. Used to set the true time the operation
|
|
begins.
|
|
|
|
@return A new census context.
|
|
*/
|
|
CENSUSAPI census_context *census_start_server_rpc_op(
|
|
const char *buffer, int64_t rpc_name_id,
|
|
const census_rpc_name_info *rpc_name_info, const char *peer, int trace_mask,
|
|
census_timestamp *start_time);
|
|
|
|
/**
|
|
Start a new, non-RPC operation. In general, this function works very
|
|
similarly to census_start_client_rpc_op, with the primary difference being
|
|
the replacement of host/path information with the more generic family/name
|
|
tags. If the context argument is non-null, then the new context will
|
|
inherit all its properties, with the following changes:
|
|
- create a new operation ID for the new context, marking it as a child of
|
|
the previous operation.
|
|
- use the family and name information for tracing and stats collection
|
|
purposes, rather than those from the original context
|
|
|
|
If the context argument is NULL, then a new root context is created. This
|
|
is particularly important for tracing purposes (the trace spans generated
|
|
will be unassociated with any other trace spans, except those
|
|
downstream). The trace_mask will be used for tracing
|
|
operations associated with the new context.
|
|
|
|
@param context The base context. Can be NULL.
|
|
@param family Family name to associate with the trace
|
|
@param name Name within family to associate with traces/stats
|
|
@param trace_mask An OR of census_trace_mask_values values. Only used if
|
|
context is NULL.
|
|
|
|
@return A new census context.
|
|
*/
|
|
CENSUSAPI census_context *census_start_op(census_context *context,
|
|
const char *family, const char *name,
|
|
int trace_mask);
|
|
|
|
/**
|
|
End an operation started by any of the census_start_*_op*() calls. The
|
|
context used in this call will no longer be valid once this function
|
|
completes.
|
|
|
|
@param context Context associated with operation which is ending.
|
|
@param status status associated with the operation. Not interpreted by
|
|
census.
|
|
*/
|
|
CENSUSAPI void census_end_op(census_context *context, int status);
|
|
|
|
#define CENSUS_TRACE_RECORD_START_OP ((uint32_t)0)
|
|
#define CENSUS_TRACE_RECORD_END_OP ((uint32_t)1)
|
|
|
|
/** Insert a trace record into the trace stream. The record consists of an
|
|
arbitrary size buffer, the size of which is provided in 'n'.
|
|
@param context Trace context
|
|
@param type User-defined type to associate with trace entry.
|
|
@param buffer Pointer to buffer to use
|
|
@param n Number of bytes in buffer
|
|
*/
|
|
CENSUSAPI void census_trace_print(census_context *context, uint32_t type,
|
|
const char *buffer, size_t n);
|
|
|
|
/** Trace record. */
|
|
typedef struct {
|
|
census_timestamp timestamp; /** Time of record creation */
|
|
uint64_t trace_id; /** Trace ID associated with record */
|
|
uint64_t op_id; /** Operation ID associated with record */
|
|
uint32_t type; /** Type (as used in census_trace_print() */
|
|
const char *buffer; /** Buffer (from census_trace_print() */
|
|
size_t buf_size; /** Number of bytes inside buffer */
|
|
} census_trace_record;
|
|
|
|
/** Start a scan of existing trace records. While a scan is ongoing, addition
|
|
of new trace records will be blocked if the underlying trace buffers
|
|
fill up, so trace processing systems should endeavor to complete
|
|
reading as soon as possible.
|
|
@param consume if non-zero, indicates that reading records also "consumes"
|
|
the previously read record - i.e. releases space in the trace log
|
|
while scanning is ongoing.
|
|
@returns 0 on success, non-zero on failure (e.g. if a scan is already ongoing)
|
|
*/
|
|
CENSUSAPI int census_trace_scan_start(int consume);
|
|
|
|
/** Get a trace record. The data pointed to by the trace buffer is guaranteed
|
|
stable until the next census_get_trace_record() call (if the consume
|
|
argument to census_trace_scan_start was non-zero) or census_trace_scan_end()
|
|
is called (otherwise).
|
|
@param trace_record structure that will be filled in with oldest trace record.
|
|
@returns -1 if an error occurred (e.g. no previous call to
|
|
census_trace_scan_start()), 0 if there is no more trace data (and
|
|
trace_record will not be modified) or 1 otherwise.
|
|
*/
|
|
CENSUSAPI int census_get_trace_record(census_trace_record *trace_record);
|
|
|
|
/** End a scan previously started by census_trace_scan_start() */
|
|
CENSUSAPI void census_trace_scan_end();
|
|
|
|
/** Core stats collection API's. The following concepts are used:
|
|
* Resource: Users record measurements for a single resource. Examples
|
|
include RPC latency, CPU seconds consumed, and bytes transmitted.
|
|
* Aggregation: An aggregation of a set of measurements. Census supports the
|
|
following aggregation types:
|
|
* Distribution - statistical distribution information, used for
|
|
recording average, standard deviation etc. Can include a histogram.
|
|
* Interval - a count of events that happen in a rolling time window.
|
|
* View: A view is a combination of a Resource, a set of tag keys and an
|
|
Aggregation. When a measurement for a Resource matches the View tags, it is
|
|
recorded (for each unique set of tag values) using the Aggregation type.
|
|
Each resource can have an arbitrary number of views by which it will be
|
|
broken down.
|
|
|
|
Census uses protos to define each of the above, and output results. This
|
|
ensures unification across the different language and runtime
|
|
implementations. The proto definitions can be found in src/proto/census.
|
|
*/
|
|
|
|
/** Define a new resource. `resource_pb` should contain an encoded Resource
|
|
protobuf, `resource_pb_size` being the size of the buffer. Returns a -ve
|
|
value on error, or a positive (>= 0) resource id (for use in
|
|
census_delete_resource() and census_record_values()). In order to be valid, a
|
|
resource must have a name, and at least one numerator in its unit type. The
|
|
resource name must be unique, and an error will be returned if it is not. */
|
|
CENSUSAPI int32_t census_define_resource(const uint8_t *resource_pb,
|
|
size_t resource_pb_size);
|
|
|
|
/** Delete a resource created by census_define_resource(). */
|
|
CENSUSAPI void census_delete_resource(int32_t resource_id);
|
|
|
|
/** Determine the id of a resource, given its name. returns -1 if the resource
|
|
does not exist. */
|
|
CENSUSAPI int32_t census_resource_id(const char *name);
|
|
|
|
/** A single value to be recorded comprises two parts: an ID for the particular
|
|
* resource and the value to be recorded against it. */
|
|
typedef struct {
|
|
int32_t resource_id;
|
|
double value;
|
|
} census_value;
|
|
|
|
/** Record new usage values against the given context. */
|
|
CENSUSAPI void census_record_values(census_context *context,
|
|
census_value *values, size_t nvalues);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* GRPC_CENSUS_H */
|