Alistair Veitch | 9686dab | 2015-05-26 14:26:47 -0700 | [diff] [blame] | 1 | /* |
| 2 | * |
Alistair Veitch | 0f69072 | 2016-01-13 09:08:38 -0800 | [diff] [blame] | 3 | * Copyright 2015-2016, Google Inc. |
Alistair Veitch | 9686dab | 2015-05-26 14:26:47 -0700 | [diff] [blame] | 4 | * All rights reserved. |
| 5 | * |
| 6 | * Redistribution and use in source and binary forms, with or without |
| 7 | * modification, are permitted provided that the following conditions are |
| 8 | * met: |
| 9 | * |
| 10 | * * Redistributions of source code must retain the above copyright |
| 11 | * notice, this list of conditions and the following disclaimer. |
| 12 | * * Redistributions in binary form must reproduce the above |
| 13 | * copyright notice, this list of conditions and the following disclaimer |
| 14 | * in the documentation and/or other materials provided with the |
| 15 | * distribution. |
| 16 | * * Neither the name of Google Inc. nor the names of its |
| 17 | * contributors may be used to endorse or promote products derived from |
| 18 | * this software without specific prior written permission. |
| 19 | * |
| 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 23 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 24 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 25 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 26 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 27 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 28 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 31 | * |
| 32 | */ |
| 33 | |
| 34 | /* RPC-internal Census API's. These are designed to be generic enough that |
| 35 | * they can (ultimately) be used in many different RPC systems (with differing |
| 36 | * implementations). */ |
| 37 | |
| 38 | #ifndef CENSUS_CENSUS_H |
| 39 | #define CENSUS_CENSUS_H |
| 40 | |
| 41 | #include <grpc/grpc.h> |
Alistair Veitch | 9686dab | 2015-05-26 14:26:47 -0700 | [diff] [blame] | 42 | |
Nicolas "Pixel" Noble | 1ed15e2 | 2015-06-09 02:24:35 +0200 | [diff] [blame] | 43 | #ifdef __cplusplus |
| 44 | extern "C" { |
| 45 | #endif |
| 46 | |
Alistair Veitch | 925e4a6 | 2015-07-26 16:51:23 -0700 | [diff] [blame] | 47 | /* Identify census features that can be enabled via census_initialize(). */ |
| 48 | enum census_features { |
| 49 | CENSUS_FEATURE_NONE = 0, /* Do not enable census. */ |
| 50 | CENSUS_FEATURE_TRACING = 1, /* Enable census tracing. */ |
| 51 | CENSUS_FEATURE_STATS = 2, /* Enable Census stats collection. */ |
| 52 | CENSUS_FEATURE_CPU = 4, /* Enable Census CPU usage collection. */ |
| 53 | CENSUS_FEATURE_ALL = |
| 54 | CENSUS_FEATURE_TRACING | CENSUS_FEATURE_STATS | CENSUS_FEATURE_CPU |
Alistair Veitch | 9686dab | 2015-05-26 14:26:47 -0700 | [diff] [blame] | 55 | }; |
| 56 | |
Alistair Veitch | a4c4d3c | 2015-07-28 14:36:22 -0700 | [diff] [blame] | 57 | /** Shutdown and startup census subsystem. The 'features' argument should be |
Alistair Veitch | 925e4a6 | 2015-07-26 16:51:23 -0700 | [diff] [blame] | 58 | * the OR (|) of census_features values. If census fails to initialize, then |
Alistair Veitch | 2696762 | 2015-06-01 10:45:54 -0700 | [diff] [blame] | 59 | * census_initialize() will return a non-zero value. It is an error to call |
| 60 | * census_initialize() more than once (without an intervening |
| 61 | * census_shutdown()). */ |
Alistair Veitch | 925e4a6 | 2015-07-26 16:51:23 -0700 | [diff] [blame] | 62 | int census_initialize(int features); |
| 63 | void census_shutdown(void); |
Alistair Veitch | 9686dab | 2015-05-26 14:26:47 -0700 | [diff] [blame] | 64 | |
Alistair Veitch | 925e4a6 | 2015-07-26 16:51:23 -0700 | [diff] [blame] | 65 | /** Return the features supported by the current census implementation (not all |
| 66 | * features will be available on all platforms). */ |
| 67 | int census_supported(void); |
| 68 | |
| 69 | /** Return the census features currently enabled. */ |
| 70 | int census_enabled(void); |
Alistair Veitch | fc62ddd | 2015-06-29 02:52:46 -0700 | [diff] [blame] | 71 | |
Alistair Veitch | e6d0ad3 | 2015-08-13 09:59:48 -0700 | [diff] [blame] | 72 | /** |
| 73 | Context is a handle used by census to represent the current tracing and |
| 74 | tagging information. Contexts should be propagated across RPC's. Contexts |
| 75 | are created by any of the census_start_*_op() functions. A context is |
| 76 | typically used as argument to most census functions. Conceptually, contexts |
| 77 | should be thought of as specific to single RPC/thread. The context can be |
| 78 | serialized for passing across the wire, via census_context_serialize(). |
| 79 | */ |
Alistair Veitch | 9686dab | 2015-05-26 14:26:47 -0700 | [diff] [blame] | 80 | typedef struct census_context census_context; |
| 81 | |
| 82 | /* This function is called by the RPC subsystem whenever it needs to get a |
| 83 | * serialized form of the current census context (presumably to pass across |
| 84 | * the wire). Arguments: |
| 85 | * 'buffer': pointer to memory into which serialized context will be placed |
| 86 | * 'buf_size': size of 'buffer' |
| 87 | * |
| 88 | * Returns: the number of bytes used in buffer if successful, or 0 if the |
| 89 | * buffer is of insufficient size. |
| 90 | * |
| 91 | * TODO(aveitch): determine how best to communicate required/max buffer size |
| 92 | * so caller doesn't have to guess. */ |
| 93 | size_t census_context_serialize(const census_context *context, char *buffer, |
| 94 | size_t buf_size); |
| 95 | |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 96 | /* Distributed traces can have a number of options. */ |
| 97 | enum census_trace_mask_values { |
Alistair Veitch | 0383d49 | 2015-07-26 15:29:00 -0700 | [diff] [blame] | 98 | CENSUS_TRACE_MASK_NONE = 0, /* Default, empty flags */ |
| 99 | CENSUS_TRACE_MASK_IS_SAMPLED = 1 /* RPC tracing enabled for this context. */ |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 100 | }; |
Alistair Veitch | 9686dab | 2015-05-26 14:26:47 -0700 | [diff] [blame] | 101 | |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 102 | /** Get the current trace mask associated with this context. The value returned |
| 103 | will be the logical or of census_trace_mask_values values. */ |
| 104 | int census_trace_mask(const census_context *context); |
Alistair Veitch | 491a9d4 | 2015-07-21 10:08:37 -0700 | [diff] [blame] | 105 | |
Alistair Veitch | e6d0ad3 | 2015-08-13 09:59:48 -0700 | [diff] [blame] | 106 | /** Set the trace mask associated with a context. */ |
| 107 | void census_set_trace_mask(int trace_mask); |
| 108 | |
| 109 | /* The concept of "operation" is a fundamental concept for Census. In an RPC |
| 110 | system, and operation typcially represents a single RPC, or a significant |
| 111 | sub-part thereof (e.g. a single logical "read" RPC to a distributed storage |
| 112 | system might do several other actions in parallel, from looking up metadata |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 113 | indices to making requests of other services - each of these could be a |
Alistair Veitch | e6d0ad3 | 2015-08-13 09:59:48 -0700 | [diff] [blame] | 114 | sub-operation with the larger RPC operation). Census uses operations for the |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 115 | following: |
Alistair Veitch | 491a9d4 | 2015-07-21 10:08:37 -0700 | [diff] [blame] | 116 | |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 117 | CPU accounting: If enabled, census will measure the thread CPU time |
| 118 | consumed between operation start and end times. |
| 119 | |
| 120 | Active operations: Census will maintain information on all currently |
| 121 | active operations. |
| 122 | |
| 123 | Distributed tracing: Each operation serves as a logical trace span. |
| 124 | |
Alistair Veitch | e6d0ad3 | 2015-08-13 09:59:48 -0700 | [diff] [blame] | 125 | Stats collection: Stats are broken down by operation (e.g. latency |
| 126 | breakdown for each unique RPC path). |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 127 | |
| 128 | The following functions serve to delineate the start and stop points for |
| 129 | each logical operation. */ |
Alistair Veitch | e6d0ad3 | 2015-08-13 09:59:48 -0700 | [diff] [blame] | 130 | |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 131 | /** |
Alistair Veitch | f886985 | 2015-08-25 15:24:49 -0700 | [diff] [blame] | 132 | This structure represents a timestamp as used by census to record the time |
| 133 | at which an operation begins. |
Alistair Veitch | e6d0ad3 | 2015-08-13 09:59:48 -0700 | [diff] [blame] | 134 | */ |
Alistair Veitch | f886985 | 2015-08-25 15:24:49 -0700 | [diff] [blame] | 135 | typedef struct { |
| 136 | /* Use gpr_timespec for default implementation. High performance |
| 137 | * implementations should use a cycle-counter based timestamp. */ |
| 138 | gpr_timespec ts; |
| 139 | } census_timestamp; |
Alistair Veitch | e6d0ad3 | 2015-08-13 09:59:48 -0700 | [diff] [blame] | 140 | |
| 141 | /** |
| 142 | Mark the beginning of an RPC operation. The information required to call the |
| 143 | functions to record the start of RPC operations (both client and server) may |
| 144 | not be callable at the true start time of the operation, due to information |
| 145 | not being available (e.g. the census context data will not be available in a |
| 146 | server RPC until at least initial metadata has been processed). To ensure |
| 147 | correct CPU accounting and latency recording, RPC systems can call this |
| 148 | function to get the timestamp of operation beginning. This can later be used |
| 149 | as an argument to census_start_{client,server}_rpc_op(). NB: for correct |
| 150 | CPU accounting, the system must guarantee that the same thread is used |
| 151 | for all request processing after this function is called. |
| 152 | |
| 153 | @return A timestamp representing the operation start time. |
| 154 | */ |
Alistair Veitch | f886985 | 2015-08-25 15:24:49 -0700 | [diff] [blame] | 155 | census_timestamp census_start_rpc_op_timestamp(void); |
Alistair Veitch | e6d0ad3 | 2015-08-13 09:59:48 -0700 | [diff] [blame] | 156 | |
| 157 | /** |
| 158 | Represent functions to map RPC name ID to service/method names. Census |
| 159 | breaks down all RPC stats by service and method names. We leave the |
| 160 | definition and format of these to the RPC system. For efficiency purposes, |
| 161 | we encode these as a single 64 bit identifier, and allow the RPC system to |
| 162 | provide a structure for functions that can convert these to service and |
| 163 | method strings. |
| 164 | |
| 165 | TODO(aveitch): Instead of providing this as an argument to the rpc_start_op() |
| 166 | functions, maybe it should be set once at census initialization. |
| 167 | */ |
| 168 | typedef struct { |
Craig Tiller | 7536af0 | 2015-12-22 13:49:30 -0800 | [diff] [blame] | 169 | const char *(*get_rpc_service_name)(int64_t id); |
| 170 | const char *(*get_rpc_method_name)(int64_t id); |
Alistair Veitch | e6d0ad3 | 2015-08-13 09:59:48 -0700 | [diff] [blame] | 171 | } census_rpc_name_info; |
| 172 | |
| 173 | /** |
| 174 | Start a client rpc operation. This function should be called as early in the |
| 175 | client RPC path as possible. This function will create a new context. If |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 176 | the context argument is non-null, then the new context will inherit all |
| 177 | its properties, with the following changes: |
| 178 | - create a new operation ID for the new context, marking it as a child of |
| 179 | the previous operation. |
Alistair Veitch | e6d0ad3 | 2015-08-13 09:59:48 -0700 | [diff] [blame] | 180 | - use the new RPC path and peer information for tracing and stats |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 181 | collection purposes, rather than those from the original context |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 182 | |
Alistair Veitch | e6d0ad3 | 2015-08-13 09:59:48 -0700 | [diff] [blame] | 183 | If the context argument is NULL, then a new root context is created. This |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 184 | is particularly important for tracing purposes (the trace spans generated |
| 185 | will be unassociated with any other trace spans, except those |
Alistair Veitch | e6d0ad3 | 2015-08-13 09:59:48 -0700 | [diff] [blame] | 186 | downstream). The trace_mask will be used for tracing operations associated |
| 187 | with the new context. |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 188 | |
Alistair Veitch | e6d0ad3 | 2015-08-13 09:59:48 -0700 | [diff] [blame] | 189 | In some RPC systems (e.g. where load balancing is used), peer information |
| 190 | may not be available at the time the operation starts. In this case, use a |
| 191 | NULL value for peer, and set it later using the |
| 192 | census_set_rpc_client_peer() function. |
| 193 | |
| 194 | @param context The parent context. Can be NULL. |
| 195 | @param rpc_name_id The rpc name identifier to be associated with this RPC. |
| 196 | @param rpc_name_info Used to decode rpc_name_id. |
| 197 | @param peer RPC peer. If not available at the time, NULL can be used, |
| 198 | and a later census_set_rpc_client_peer() call made. |
| 199 | @param trace_mask An OR of census_trace_mask_values values. Only used in |
| 200 | the creation of a new root context (context == NULL). |
| 201 | @param start_time A timestamp returned from census_start_rpc_op_timestamp(). |
| 202 | Can be NULL. Used to set the true time the operation |
| 203 | begins. |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 204 | |
| 205 | @return A new census context. |
| 206 | */ |
Alistair Veitch | e6d0ad3 | 2015-08-13 09:59:48 -0700 | [diff] [blame] | 207 | census_context *census_start_client_rpc_op( |
Craig Tiller | 7536af0 | 2015-12-22 13:49:30 -0800 | [diff] [blame] | 208 | const census_context *context, int64_t rpc_name_id, |
Alistair Veitch | e6d0ad3 | 2015-08-13 09:59:48 -0700 | [diff] [blame] | 209 | const census_rpc_name_info *rpc_name_info, const char *peer, int trace_mask, |
| 210 | const census_timestamp *start_time); |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 211 | |
| 212 | /** |
Alistair Veitch | e6d0ad3 | 2015-08-13 09:59:48 -0700 | [diff] [blame] | 213 | Add peer information to a context representing a client RPC operation. |
| 214 | */ |
| 215 | void census_set_rpc_client_peer(census_context *context, const char *peer); |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 216 | |
Alistair Veitch | e6d0ad3 | 2015-08-13 09:59:48 -0700 | [diff] [blame] | 217 | /** |
| 218 | Start a server RPC operation. Returns a new context to be used in future |
| 219 | census calls. If buffer is non-NULL, then the buffer contents should |
| 220 | represent the client context, as generated by census_context_serialize(). |
| 221 | If buffer is NULL, a new root context is created. |
| 222 | |
| 223 | @param buffer Buffer containing bytes output from census_context_serialize(). |
| 224 | @param rpc_name_id The rpc name identifier to be associated with this RPC. |
| 225 | @param rpc_name_info Used to decode rpc_name_id. |
| 226 | @param peer RPC peer. |
| 227 | @param trace_mask An OR of census_trace_mask_values values. Only used in |
| 228 | the creation of a new root context (buffer == NULL). |
| 229 | @param start_time A timestamp returned from census_start_rpc_op_timestamp(). |
| 230 | Can be NULL. Used to set the true time the operation |
| 231 | begins. |
| 232 | |
| 233 | @return A new census context. |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 234 | */ |
Alistair Veitch | e6d0ad3 | 2015-08-13 09:59:48 -0700 | [diff] [blame] | 235 | census_context *census_start_server_rpc_op( |
Craig Tiller | 7536af0 | 2015-12-22 13:49:30 -0800 | [diff] [blame] | 236 | const char *buffer, int64_t rpc_name_id, |
Alistair Veitch | e6d0ad3 | 2015-08-13 09:59:48 -0700 | [diff] [blame] | 237 | const census_rpc_name_info *rpc_name_info, const char *peer, int trace_mask, |
| 238 | census_timestamp *start_time); |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 239 | |
| 240 | /** |
Alistair Veitch | e6d0ad3 | 2015-08-13 09:59:48 -0700 | [diff] [blame] | 241 | Start a new, non-RPC operation. In general, this function works very |
| 242 | similarly to census_start_client_rpc_op, with the primary difference being |
| 243 | the replacement of host/path information with the more generic family/name |
| 244 | tags. If the context argument is non-null, then the new context will |
| 245 | inherit all its properties, with the following changes: |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 246 | - create a new operation ID for the new context, marking it as a child of |
| 247 | the previous operation. |
| 248 | - use the family and name information for tracing and stats collection |
| 249 | purposes, rather than those from the original context |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 250 | |
Alistair Veitch | e6d0ad3 | 2015-08-13 09:59:48 -0700 | [diff] [blame] | 251 | If the context argument is NULL, then a new root context is created. This |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 252 | is particularly important for tracing purposes (the trace spans generated |
| 253 | will be unassociated with any other trace spans, except those |
Alistair Veitch | e6d0ad3 | 2015-08-13 09:59:48 -0700 | [diff] [blame] | 254 | downstream). The trace_mask will be used for tracing |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 255 | operations associated with the new context. |
| 256 | |
| 257 | @param context The base context. Can be NULL. |
| 258 | @param family Family name to associate with the trace |
| 259 | @param name Name within family to associated with traces/stats |
Alistair Veitch | e6d0ad3 | 2015-08-13 09:59:48 -0700 | [diff] [blame] | 260 | @param trace_mask An OR of census_trace_mask_values values. Only used if |
| 261 | context is NULL. |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 262 | |
| 263 | @return A new census context. |
| 264 | */ |
| 265 | census_context *census_start_op(census_context *context, const char *family, |
Alistair Veitch | e6d0ad3 | 2015-08-13 09:59:48 -0700 | [diff] [blame] | 266 | const char *name, int trace_mask); |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 267 | |
Alistair Veitch | 0879df2 | 2015-08-13 14:32:05 -0700 | [diff] [blame] | 268 | /** |
| 269 | End an operation started by any of the census_start_*_op*() calls. The |
| 270 | context used in this call will no longer be valid once this function |
| 271 | completes. |
| 272 | |
| 273 | @param context Context associated with operation which is ending. |
| 274 | @param status status associated with the operation. Not interpreted by |
| 275 | census. |
| 276 | */ |
Alistair Veitch | e6d0ad3 | 2015-08-13 09:59:48 -0700 | [diff] [blame] | 277 | void census_end_op(census_context *context, int status); |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 278 | |
Craig Tiller | 7536af0 | 2015-12-22 13:49:30 -0800 | [diff] [blame] | 279 | #define CENSUS_TRACE_RECORD_START_OP ((uint32_t)0) |
| 280 | #define CENSUS_TRACE_RECORD_END_OP ((uint32_t)1) |
Alistair Veitch | 6afe53f | 2015-08-28 14:05:15 -0700 | [diff] [blame] | 281 | |
Alistair Veitch | af5002f | 2015-07-26 15:11:50 -0700 | [diff] [blame] | 282 | /** Insert a trace record into the trace stream. The record consists of an |
Alistair Veitch | 6afe53f | 2015-08-28 14:05:15 -0700 | [diff] [blame] | 283 | arbitrary size buffer, the size of which is provided in 'n'. |
| 284 | @param context Trace context |
| 285 | @param type User-defined type to associate with trace entry. |
| 286 | @param buffer Pointer to buffer to use |
| 287 | @param n Number of bytes in buffer |
| 288 | */ |
Craig Tiller | 7536af0 | 2015-12-22 13:49:30 -0800 | [diff] [blame] | 289 | void census_trace_print(census_context *context, uint32_t type, |
Alistair Veitch | 6afe53f | 2015-08-28 14:05:15 -0700 | [diff] [blame] | 290 | const char *buffer, size_t n); |
| 291 | |
| 292 | /** Trace record. */ |
| 293 | typedef struct { |
| 294 | census_timestamp timestamp; /* Time of record creation */ |
Craig Tiller | 7536af0 | 2015-12-22 13:49:30 -0800 | [diff] [blame] | 295 | uint64_t trace_id; /* Trace ID associated with record */ |
| 296 | uint64_t op_id; /* Operation ID associated with record */ |
| 297 | uint32_t type; /* Type (as used in census_trace_print() */ |
Alistair Veitch | 6afe53f | 2015-08-28 14:05:15 -0700 | [diff] [blame] | 298 | const char *buffer; /* Buffer (from census_trace_print() */ |
| 299 | size_t buf_size; /* Number of bytes inside buffer */ |
| 300 | } census_trace_record; |
| 301 | |
| 302 | /** Start a scan of existing trace records. While a scan is ongoing, addition |
| 303 | of new trace records will be blocked if the underlying trace buffers |
| 304 | fill up, so trace processing systems should endeavor to complete |
| 305 | reading as soon as possible. |
| 306 | @param consume if non-zero, indicates that reading records also "consumes" |
| 307 | the previously read record - i.e. releases space in the trace log |
| 308 | while scanning is ongoing. |
| 309 | @returns 0 on success, non-zero on failure (e.g. if a scan is already ongoing) |
| 310 | */ |
| 311 | int census_trace_scan_start(int consume); |
| 312 | |
| 313 | /** Get a trace record. The data pointed to by the trace buffer is guaranteed |
| 314 | stable until the next census_get_trace_record() call (if the consume |
| 315 | argument to census_trace_scan_start was non-zero) or census_trace_scan_end() |
| 316 | is called (otherwise). |
| 317 | @param trace_record structure that will be filled in with oldest trace record. |
| 318 | @returns -1 if an error occurred (e.g. no previous call to |
| 319 | census_trace_scan_start()), 0 if there is no more trace data (and |
| 320 | trace_record will not be modified) or 1 otherwise. |
| 321 | */ |
| 322 | int census_get_trace_record(census_trace_record *trace_record); |
| 323 | |
| 324 | /** End a scan previously started by census_trace_scan_start() */ |
| 325 | void census_trace_scan_end(); |
Alistair Veitch | 9686dab | 2015-05-26 14:26:47 -0700 | [diff] [blame] | 326 | |
Alistair Veitch | f68bf38 | 2015-07-28 14:27:28 -0700 | [diff] [blame] | 327 | /* A Census tag set is a collection of key:value string pairs; these form the |
| 328 | basis against which Census metrics will be recorded. Keys are unique within |
| 329 | a tag set. All contexts have an associated tag set. */ |
| 330 | typedef struct census_tag_set census_tag_set; |
| 331 | |
Alistair Veitch | bb30d25 | 2016-01-12 17:36:05 -0800 | [diff] [blame] | 332 | /* A tag is a key:value pair. The key is a printable, nil-terminate |
| 333 | string. The value is a binary string, that may be printable. There are no |
| 334 | limits on the sizes of either keys or values, but code authors should |
| 335 | remember that systems may have inbuilt limits (e.g. for propagated tags, |
| 336 | the bytes on the wire) and that larger tags means more memory consumed and |
| 337 | time in processing. */ |
| 338 | typedef struct { |
| 339 | const char *key; |
| 340 | const char *value; |
| 341 | size_t value_len; |
Alistair Veitch | 0f69072 | 2016-01-13 09:08:38 -0800 | [diff] [blame] | 342 | uint8_t flags; |
Alistair Veitch | bb30d25 | 2016-01-12 17:36:05 -0800 | [diff] [blame] | 343 | } census_tag; |
Alistair Veitch | f68bf38 | 2015-07-28 14:27:28 -0700 | [diff] [blame] | 344 | |
Alistair Veitch | bb30d25 | 2016-01-12 17:36:05 -0800 | [diff] [blame] | 345 | /* Tag flags. */ |
| 346 | #define CENSUS_TAG_PROPAGATE 1 /* Tag should be propagated over RPC */ |
| 347 | #define CENSUS_TAG_STATS 2 /* Tag will be used for statistics aggregation */ |
| 348 | #define CENSUS_TAG_BINARY 4 /* Tag value is not printable */ |
| 349 | #define CENSUS_TAG_RESERVED 8 /* Reserved for internal use. */ |
| 350 | /* Flag values 8,16,32,64,128 are reserved for future/internal use. Clients |
| 351 | should not use or rely on their values. */ |
Alistair Veitch | f68bf38 | 2015-07-28 14:27:28 -0700 | [diff] [blame] | 352 | |
Alistair Veitch | bb30d25 | 2016-01-12 17:36:05 -0800 | [diff] [blame] | 353 | #define CENSUS_TAG_IS_PROPAGATED(flags) (flags & CENSUS_TAG_PROPAGATE) |
| 354 | #define CENSUS_TAG_IS_STATS(flags) (flags & CENSUS_TAG_STATS) |
| 355 | #define CENSUS_TAG_IS_BINARY(flags) (flags & CENSUS_TAG_BINARY) |
| 356 | |
| 357 | #define CENSUS_MAX_TAG_KV_LEN 255 /* Maximum length of key/value in a tag. */ |
| 358 | #define CENSUS_MAX_TAGS 255 /* Maximum number of tags in a tag set. */ |
| 359 | |
| 360 | /* Create a new tag set, adding and removing tags from an existing tag set. |
| 361 | @param base Base tag set to build upon. Can be NULL. |
| 362 | @param tags A set of tags to be added/changed/deleted. Tags with keys that |
| 363 | are in 'tags', but not 'base', are added to the tag set. Keys that are in |
| 364 | both 'tags' and 'base' will have their value replaced. Tags with keys in |
| 365 | both, but with NULL or zero-length values, will be deleted from the |
| 366 | tag set. |
| 367 | @param ntags number of tags in 'tags' |
| 368 | */ |
| 369 | census_tag_set *census_tag_set_create(const census_tag_set *base, |
| 370 | const census_tag *tags, int ntags); |
| 371 | |
| 372 | /* Destroy a tag set created by census_tag_set_create(). Once this function |
| 373 | has been called, the tag set cannot be reused. */ |
Alistair Veitch | f68bf38 | 2015-07-28 14:27:28 -0700 | [diff] [blame] | 374 | void census_tag_set_destroy(census_tag_set *tags); |
| 375 | |
Alistair Veitch | bb30d25 | 2016-01-12 17:36:05 -0800 | [diff] [blame] | 376 | /* Get the number of tags in the tag set. */ |
| 377 | int census_tag_set_ntags(const census_tag_set *tags); |
| 378 | |
| 379 | /* Get a tag by it's index in the tag set. Returns 0 if the index is invalid |
| 380 | (<0 or >= census_tag_set_ntags). There is no guarantee on tag ordering. */ |
| 381 | int census_tag_set_get_tag_by_index(const census_tag_set *tags, int index, |
| 382 | census_tag *tag); |
| 383 | |
| 384 | /* Get a tag by its key. Returns 0 if the key is not present in the tag |
| 385 | set. */ |
| 386 | int census_tag_set_get_tag_by_key(const census_tag_set *tags, const char *key, |
| 387 | census_tag *tag); |
| 388 | |
Alistair Veitch | 0f69072 | 2016-01-13 09:08:38 -0800 | [diff] [blame] | 389 | /* Encode to-be-propagated non-binary tags from a tag set into a memory |
| 390 | buffer. The total number of bytes used in the buffer is returned. If the |
| 391 | buffer is too small to contain the encoded tag set, then 0 is returned. */ |
| 392 | size_t census_tag_set_encode_propagated(const census_tag_set *tags, |
| 393 | char *buffer, size_t buf_size); |
| 394 | |
| 395 | /* Encode to-be-propagated binary tags from a tag set into a memory |
| 396 | buffer. The total number of bytes used in the buffer is returned. If the |
| 397 | buffer is too small to contain the encoded tag set, then 0 is returned. */ |
| 398 | size_t census_tag_set_encode_propagated_binary(const census_tag_set *tags, |
| 399 | char *buffer, size_t buf_size); |
| 400 | |
| 401 | /* Decode tag set buffers encoded with census_tag_set_encode_*(). */ |
| 402 | census_tag_set *census_tag_set_decode(const char *buffer, size_t size, |
| 403 | const char *bin_buffer, size_t bin_size); |
| 404 | |
Alistair Veitch | f68bf38 | 2015-07-28 14:27:28 -0700 | [diff] [blame] | 405 | /* Get a contexts tag set. */ |
| 406 | census_tag_set *census_context_tag_set(census_context *context); |
| 407 | |
Alistair Veitch | e62f68c | 2015-08-27 16:24:27 -0700 | [diff] [blame] | 408 | /* Core stats collection API's. The following concepts are used: |
Alistair Veitch | 9a09982 | 2015-08-27 13:16:00 -0700 | [diff] [blame] | 409 | * Aggregation: A collection of values. Census supports the following |
| 410 | aggregation types: |
Alistair Veitch | aafe972 | 2015-08-31 13:15:00 -0700 | [diff] [blame] | 411 | Sum - a single summation type. Typically used for keeping (e.g.) |
Alistair Veitch | 9a09982 | 2015-08-27 13:16:00 -0700 | [diff] [blame] | 412 | counts of events. |
| 413 | Distribution - statistical distribution information, used for |
| 414 | recording average, standard deviation etc. |
| 415 | Histogram - a histogram of measurements falling in defined bucket |
| 416 | boundaries. |
| 417 | Window - a count of events that happen in reolling time window. |
| 418 | New aggregation types can be added by the user, if desired (see |
| 419 | census_register_aggregation()). |
| 420 | * Metric: Each measurement is for a single metric. Examples include RPC |
| 421 | latency, CPU seconds consumed, and bytes transmitted. |
Alistair Veitch | b855202 | 2015-08-28 10:54:17 -0700 | [diff] [blame] | 422 | * View: A view is a combination of a metric, a tag set (in which the tag |
| 423 | values are regular expressions) and a set of aggregations. When a |
| 424 | measurement for a metric matches the view tags, it is recorded (for each |
| 425 | unique set of tags) against each aggregation. Each metric can have an |
| 426 | arbitrary number of views by which it will be broken down. |
Alistair Veitch | 9a09982 | 2015-08-27 13:16:00 -0700 | [diff] [blame] | 427 | */ |
| 428 | |
| 429 | /* A single value to be recorded comprises two parts: an ID for the particular |
| 430 | * metric and the value to be recorded against it. */ |
Alistair Veitch | 851032a | 2015-07-20 11:59:13 -0700 | [diff] [blame] | 431 | typedef struct { |
Craig Tiller | 7536af0 | 2015-12-22 13:49:30 -0800 | [diff] [blame] | 432 | uint32_t metric_id; |
Alistair Veitch | 851032a | 2015-07-20 11:59:13 -0700 | [diff] [blame] | 433 | double value; |
Alistair Veitch | 9a09982 | 2015-08-27 13:16:00 -0700 | [diff] [blame] | 434 | } census_value; |
Alistair Veitch | 851032a | 2015-07-20 11:59:13 -0700 | [diff] [blame] | 435 | |
Alistair Veitch | 9a09982 | 2015-08-27 13:16:00 -0700 | [diff] [blame] | 436 | /* Record new usage values against the given context. */ |
Alistair Veitch | 5b61479 | 2015-08-31 08:43:37 -0700 | [diff] [blame] | 437 | void census_record_values(census_context *context, census_value *values, |
| 438 | size_t nvalues); |
Alistair Veitch | 4d1589a | 2015-07-17 15:13:04 -0700 | [diff] [blame] | 439 | |
Alistair Veitch | 1c09acc | 2015-08-31 16:57:32 -0700 | [diff] [blame] | 440 | /** Type representing a particular aggregation */ |
| 441 | typedef struct census_aggregation_ops census_aggregation_ops; |
Alistair Veitch | ade0021 | 2015-08-25 15:00:26 -0700 | [diff] [blame] | 442 | |
Alistair Veitch | 1c09acc | 2015-08-31 16:57:32 -0700 | [diff] [blame] | 443 | /* Predefined aggregation types, for use with census_view_create(). */ |
Alistair Veitch | aafe972 | 2015-08-31 13:15:00 -0700 | [diff] [blame] | 444 | extern census_aggregation_ops census_agg_sum; |
Alistair Veitch | a24148e | 2015-08-31 08:30:32 -0700 | [diff] [blame] | 445 | extern census_aggregation_ops census_agg_distribution; |
| 446 | extern census_aggregation_ops census_agg_histogram; |
| 447 | extern census_aggregation_ops census_agg_window; |
Alistair Veitch | ade0021 | 2015-08-25 15:00:26 -0700 | [diff] [blame] | 448 | |
Alistair Veitch | 9a09982 | 2015-08-27 13:16:00 -0700 | [diff] [blame] | 449 | /** Information needed to instantiate a new aggregation. Used in view |
| 450 | construction via census_define_view(). */ |
| 451 | typedef struct { |
Alistair Veitch | a24148e | 2015-08-31 08:30:32 -0700 | [diff] [blame] | 452 | const census_aggregation_ops *ops; |
Alistair Veitch | bb30d25 | 2016-01-12 17:36:05 -0800 | [diff] [blame] | 453 | const void |
| 454 | *create_arg; /* Argument to be used for aggregation initialization. */ |
Alistair Veitch | a24148e | 2015-08-31 08:30:32 -0700 | [diff] [blame] | 455 | } census_aggregation; |
Alistair Veitch | ade0021 | 2015-08-25 15:00:26 -0700 | [diff] [blame] | 456 | |
Alistair Veitch | b855202 | 2015-08-28 10:54:17 -0700 | [diff] [blame] | 457 | /** A census view type. Opaque. */ |
Alistair Veitch | 9a09982 | 2015-08-27 13:16:00 -0700 | [diff] [blame] | 458 | typedef struct census_view census_view; |
Alistair Veitch | ade0021 | 2015-08-25 15:00:26 -0700 | [diff] [blame] | 459 | |
Alistair Veitch | 9a09982 | 2015-08-27 13:16:00 -0700 | [diff] [blame] | 460 | /** Create a new view. |
Alistair Veitch | e62f68c | 2015-08-27 16:24:27 -0700 | [diff] [blame] | 461 | @param metric_id Metric with which this view is associated. |
Alistair Veitch | 9a09982 | 2015-08-27 13:16:00 -0700 | [diff] [blame] | 462 | @param tags tags that define the view |
| 463 | @param aggregations aggregations to associate with the view |
| 464 | @param naggregations number of aggregations |
| 465 | |
| 466 | @return A new census view |
Alistair Veitch | ade0021 | 2015-08-25 15:00:26 -0700 | [diff] [blame] | 467 | */ |
Craig Tiller | 7536af0 | 2015-12-22 13:49:30 -0800 | [diff] [blame] | 468 | census_view *census_view_create(uint32_t metric_id, const census_tag_set *tags, |
Alistair Veitch | a24148e | 2015-08-31 08:30:32 -0700 | [diff] [blame] | 469 | const census_aggregation *aggregations, |
| 470 | size_t naggregations); |
Alistair Veitch | b855202 | 2015-08-28 10:54:17 -0700 | [diff] [blame] | 471 | |
| 472 | /** Destroy a previously created view. */ |
| 473 | void census_view_delete(census_view *view); |
Alistair Veitch | ade0021 | 2015-08-25 15:00:26 -0700 | [diff] [blame] | 474 | |
Alistair Veitch | e62f68c | 2015-08-27 16:24:27 -0700 | [diff] [blame] | 475 | /** Metric ID associated with a view */ |
| 476 | size_t census_view_metric(const census_view *view); |
| 477 | |
Alistair Veitch | 9a09982 | 2015-08-27 13:16:00 -0700 | [diff] [blame] | 478 | /** Number of aggregations associated with view. */ |
| 479 | size_t census_view_naggregations(const census_view *view); |
Alistair Veitch | ade0021 | 2015-08-25 15:00:26 -0700 | [diff] [blame] | 480 | |
Alistair Veitch | 9a09982 | 2015-08-27 13:16:00 -0700 | [diff] [blame] | 481 | /** Get tags associated with view. */ |
| 482 | const census_tag_set *census_view_tags(const census_view *view); |
| 483 | |
Alistair Veitch | b855202 | 2015-08-28 10:54:17 -0700 | [diff] [blame] | 484 | /** Get aggregation descriptors associated with a view. */ |
Alistair Veitch | a24148e | 2015-08-31 08:30:32 -0700 | [diff] [blame] | 485 | const census_aggregation *census_view_aggregrations(const census_view *view); |
Alistair Veitch | ade0021 | 2015-08-25 15:00:26 -0700 | [diff] [blame] | 486 | |
Alistair Veitch | 9a09982 | 2015-08-27 13:16:00 -0700 | [diff] [blame] | 487 | /** Holds all the aggregation data for a particular view instantiation. Forms |
Alistair Veitch | b855202 | 2015-08-28 10:54:17 -0700 | [diff] [blame] | 488 | part of the data returned by census_view_data(). */ |
Alistair Veitch | 9a09982 | 2015-08-27 13:16:00 -0700 | [diff] [blame] | 489 | typedef struct { |
Alistair Veitch | b855202 | 2015-08-28 10:54:17 -0700 | [diff] [blame] | 490 | const census_tag_set *tags; /* Tags for this set of aggregations. */ |
| 491 | const void **data; /* One data set for every aggregation in the view. */ |
Alistair Veitch | 9a09982 | 2015-08-27 13:16:00 -0700 | [diff] [blame] | 492 | } census_view_aggregation_data; |
Alistair Veitch | ade0021 | 2015-08-25 15:00:26 -0700 | [diff] [blame] | 493 | |
Alistair Veitch | b855202 | 2015-08-28 10:54:17 -0700 | [diff] [blame] | 494 | /** Census view data as returned by census_view_get_data(). */ |
Alistair Veitch | 9a09982 | 2015-08-27 13:16:00 -0700 | [diff] [blame] | 495 | typedef struct { |
Alistair Veitch | e62f68c | 2015-08-27 16:24:27 -0700 | [diff] [blame] | 496 | size_t n_tag_sets; /* Number of unique tag sets that matched view. */ |
Alistair Veitch | 9a09982 | 2015-08-27 13:16:00 -0700 | [diff] [blame] | 497 | const census_view_aggregation_data *data; /* n_tag_sets entries */ |
| 498 | } census_view_data; |
Alistair Veitch | ade0021 | 2015-08-25 15:00:26 -0700 | [diff] [blame] | 499 | |
Alistair Veitch | 9a09982 | 2015-08-27 13:16:00 -0700 | [diff] [blame] | 500 | /** Get data from aggregations associated with a view. |
Alistair Veitch | e62f68c | 2015-08-27 16:24:27 -0700 | [diff] [blame] | 501 | @param view View from which to get data. |
Alistair Veitch | b855202 | 2015-08-28 10:54:17 -0700 | [diff] [blame] | 502 | @return Full set of data for all aggregations for the view. |
Alistair Veitch | 9a09982 | 2015-08-27 13:16:00 -0700 | [diff] [blame] | 503 | */ |
Alistair Veitch | b855202 | 2015-08-28 10:54:17 -0700 | [diff] [blame] | 504 | const census_view_data *census_view_get_data(const census_view *view); |
Alistair Veitch | 9a09982 | 2015-08-27 13:16:00 -0700 | [diff] [blame] | 505 | |
Alistair Veitch | b855202 | 2015-08-28 10:54:17 -0700 | [diff] [blame] | 506 | /** Reset all view data to zero for the specified view */ |
| 507 | void census_view_reset(census_view *view); |
Alistair Veitch | ade0021 | 2015-08-25 15:00:26 -0700 | [diff] [blame] | 508 | |
Nicolas "Pixel" Noble | 1ed15e2 | 2015-06-09 02:24:35 +0200 | [diff] [blame] | 509 | #ifdef __cplusplus |
| 510 | } |
| 511 | #endif |
| 512 | |
Alistair Veitch | 9686dab | 2015-05-26 14:26:47 -0700 | [diff] [blame] | 513 | #endif /* CENSUS_CENSUS_H */ |