#ifndef LIBOBOE_H #define LIBOBOE_H #ifdef __cplusplus extern "C" { #endif #include #include #include #include "bson/bson.h" #include "oboe_debug.h" /** Compile time debug logging detail level - cannot log more detailed than this. */ #define OBOE_DEBUG_LEVEL OBOE_DEBUG_HIGH /** * Default configuration settings update interval in seconds. * * Borrowed from the Tracelyzer's oboe.h. */ #define OBOE_DEFAULT_SETTINGS_INTERVAL 30 /** * Default heartbeat status update interval in seconds. */ #define OBOE_DEFAULT_HEARTBEAT_INTERVAL 60 /** * Default keepalive interval in seconds. * * A keepalive message will be sent after communications are idle for this interval. */ #define OBOE_DEFAULT_KEEPALIVE_INTERVAL 20 #define OBOE_SAMPLE_RATE_DEFAULT 300000 // 30% #define OBOE_SAMPLE_RESOLUTION 1000000 #define OBOE_MAX_TASK_ID_LEN 20 #define OBOE_MAX_OP_ID_LEN 8 #define OBOE_MAX_METADATA_PACK_LEN 512 #define XTR_CURRENT_VERSION 1 #define XTR_UDP_PORT 7831 #define OBOE_REPORTER_PROTOCOL_FILE "file" #define OBOE_REPORTER_PROTOCOL_UDP "udp" #define OBOE_REPORTER_PROTOCOL_SSL "ssl" #define OBOE_REPORTER_PROTOCOL_DEFAULT OBOE_REPORTER_PROTOCOL_UDP /** Maximum reasonable length of an arguments string for configuring a reporter. */ #define OBOE_REPORTER_ARGS_SIZE 4000 // structs typedef struct oboe_ids { uint8_t task_id[OBOE_MAX_TASK_ID_LEN]; uint8_t op_id[OBOE_MAX_OP_ID_LEN]; } oboe_ids_t; typedef struct oboe_metadata { oboe_ids_t ids; size_t task_len; size_t op_len; } oboe_metadata_t; typedef struct oboe_event { oboe_metadata_t metadata; bson_buffer bbuf; char * bb_str; } oboe_event_t; // oboe_metadata int oboe_metadata_init (oboe_metadata_t *); int oboe_metadata_destroy (oboe_metadata_t *); int oboe_metadata_is_valid (const oboe_metadata_t *); void oboe_metadata_copy (oboe_metadata_t *, const oboe_metadata_t *); void oboe_metadata_random (oboe_metadata_t *); int oboe_metadata_set_lengths (oboe_metadata_t *, size_t, size_t); int oboe_metadata_create_event (const oboe_metadata_t *, oboe_event_t *); int oboe_metadata_tostr (const oboe_metadata_t *, char *, size_t); int oboe_metadata_fromstr (oboe_metadata_t *, const char *, size_t); // oboe_event int oboe_event_init (oboe_event_t *, const oboe_metadata_t *); int oboe_event_destroy (oboe_event_t *); int oboe_event_add_info (oboe_event_t *, const char *, const char *); int oboe_event_add_info_binary (oboe_event_t *, const char *, const char *, size_t); int oboe_event_add_info_int64 (oboe_event_t *, const char *, const int64_t); int oboe_event_add_info_double (oboe_event_t *, const char *, const double); int oboe_event_add_info_bool (oboe_event_t *, const char *, const int); int oboe_event_add_info_fmt (oboe_event_t *, const char *key, const char *fmt, ...); int oboe_event_add_info_bson (oboe_event_t *, const char *key, const bson *val); int oboe_event_add_edge (oboe_event_t *, const oboe_metadata_t *); int oboe_event_add_edge_fromstr(oboe_event_t *, const char *, size_t); /** * Send event message using the default reporter. * * @param evt The event message. * @param md The X-Trace metadata. * @return Length of message sent in bytes on success; otherwise -1. */ int oboe_event_send(oboe_event_t *evt, oboe_metadata_t *md); // oboe_context oboe_metadata_t *oboe_context_get(); void oboe_context_set(oboe_metadata_t *); int oboe_context_set_fromstr(const char *, size_t); void oboe_context_clear(); int oboe_context_is_valid(); // oboe_reporter struct oboe_reporter; typedef ssize_t (*reporter_send)(void *, const char *, size_t); typedef int (*reporter_destroy)(void *); typedef struct oboe_reporter { void * descriptor; /*!< Reporter's context. */ // const char * protocol; /*!< Copy of the protocol string. */ // const char * args; /*!< Copy of the initialization arguement string. */ reporter_send send; /*!< Send a trace event message. */ reporter_destroy destroy; /*!< Destroy the reporter - release all resources. */ // reporter_ready ready; /*!< Check if the reporter is ready for another trace. Used by oboe_sample_request(). */ // reporter_disconnect disconnect; /*!< Disconnect reporter's connections. */ // reporter_reconnect reconnect; /*!< Restart/re-initialize reporter's connections. */ } oboe_reporter_t; int oboe_reporter_udp_init (oboe_reporter_t *, const char *, const char *); int oboe_reporter_udp_init_str(oboe_reporter_t *, const char *); int oboe_reporter_file_init (oboe_reporter_t *, const char *); int oboe_reporter_file_init_str(oboe_reporter_t *, const char *); int oboe_reporter_ssl_init (oboe_reporter_t *, const char *); /** * Initialize a reporter structure for use with the specified protocol. * * @param rep Pointer to an uninitialized reporter structure. * @param protocol One of OBOE_REPORTER_PROTOCOL_FILE, OBOE_REPORTER_PROTOCOL_UDP, * or OBOE_REPORTER_PROTOCOL_SSL. * @param args A configuration string for the specified protocol (protocol dependent syntax). * @return Zero on success; otherwise -1. */ int oboe_reporter_init (oboe_reporter_t *rep, const char *protocol, const char *args); /** * Check if the reporter is ready to send. * * The concept of 'ready' is depends on the specific reporter being used. * * @param rep The reporter context (optional). * @return Non-zero if the reporter is ready to send. */ int oboe_reporter_is_ready(oboe_reporter_t *rep); /** * Send an event message using the selected reporter context. * * @param rep The reporter context. * @param evt The event message. * @param md The X-Trace metadata. * @return Length of message sent in bytes on success; otherwise -1. */ int oboe_reporter_send(oboe_reporter_t *rep, oboe_metadata_t *md, oboe_event_t *evt); /** * Release any resources held by the reporter context. * * @param rep Pointer to a reporter context structure. * @return Zero on success; otherwise non-zero to indicate an error. */ int oboe_reporter_destroy(oboe_reporter_t *rep); /** * Disconnect or shut down the Oboe reporter, but allow it to be reconnect()ed. * * @param rep Pointer to the active reporter object. */ void oboe_disconnect(oboe_reporter_t *rep); /** * Reconnect or restart the Oboe reporter. * * @param rep Pointer to the active reporter object. */ void oboe_reconnect(oboe_reporter_t *rep); /* Deprecated? Use oboe_reporter_send() */ ssize_t oboe_reporter_udp_send(void *desc, const char *data, size_t len); // initialization /** * Initialize the Oboe subsystems. * * This should be called before any other oboe_* functions. However, in order * to make the library easier to work with, checks are in place so that it * will be called by any of the other functions that depend on it. * * Note that while calling this will be handled automatically, the application * must still initialize one of the reporters directly since each reporter * requires unique parameters. The use of oboe_reporter_init() is recommended * so that the selection of the reporter and values for its configuration * parameters */ void oboe_init(); /** * Shut down the Oboe subsystems. * * This may be called on exit in order to release any resources held by * the Oboe library including any child threads. */ void oboe_shutdown(); // Settings interface #define OBOE_SETTINGS_VERSION 1 #define OBOE_SETTINGS_MAGIC_NUMBER 0x6f626f65 #define OBOE_SETTINGS_TYPE_SKIP 0 #define OBOE_SETTINGS_TYPE_STOP 1 #define OBOE_SETTINGS_TYPE_DEFAULT_SAMPLE_RATE 2 #define OBOE_SETTINGS_TYPE_LAYER_SAMPLE_RATE 3 #define OBOE_SETTINGS_TYPE_LAYER_APP_SAMPLE_RATE 4 #define OBOE_SETTINGS_TYPE_LAYER_HTTPHOST_SAMPLE_RATE 5 #define OBOE_SETTINGS_TYPE_CONFIG_STRING 6 #define OBOE_SETTINGS_TYPE_CONFIG_INT 7 #define OBOE_SETTINGS_FLAG_OK 0x0 #define OBOE_SETTINGS_FLAG_INVALID 0x1 #define OBOE_SETTINGS_FLAG_OVERRIDE 0x2 #define OBOE_SETTINGS_FLAG_SAMPLE_START 0x4 #define OBOE_SETTINGS_FLAG_SAMPLE_THROUGH 0x8 #define OBOE_SETTINGS_FLAG_SAMPLE_THROUGH_ALWAYS 0x10 #define OBOE_SETTINGS_FLAG_SAMPLE_AVW_ALWAYS 0x20 #define OBOE_SETTINGS_MAX_STRLEN 256 #define OBOE_SETTINGS_UNSET -1 #define OBOE_SETTINGS_MIN_REFRESH_INTERVAL 30 // Value for "SampleSource" info key // where was the sample rate specified? (oboe settings, config file, hard-coded default, etc) #define OBOE_SAMPLE_RATE_SOURCE_FILE 1 #define OBOE_SAMPLE_RATE_SOURCE_DEFAULT 2 #define OBOE_SAMPLE_RATE_SOURCE_OBOE 3 #define OBOE_SAMPLE_RATE_SOURCE_LAST_OBOE 4 #define OBOE_SAMPLE_RATE_SOURCE_DEFAULT_MISCONFIGURED 5 #define OBOE_SAMPLE_RATE_SOURCE_OBOE_DEFAULT 6 #define OBOE_SAMPLE_RESOLUTION 1000000 // Used to convert to settings flags: #define OBOE_TRACE_NEVER 0 #define OBOE_TRACE_ALWAYS 1 #define OBOE_TRACE_THROUGH 2 typedef struct { volatile uint32_t magic; volatile uint32_t timestamp; volatile uint16_t type; volatile uint16_t flags; volatile uint32_t value; uint32_t _pad; char layer[OBOE_SETTINGS_MAX_STRLEN]; char arg[OBOE_SETTINGS_MAX_STRLEN]; } __attribute__((packed)) oboe_settings_t; // Current settings configuration: typedef struct { int tracing_mode; // loaded from config file int sample_rate; // loaded from config file int default_sample_rate; // default sample rate (fallback) // oboe_reporter_t *reporter; // the initialized event reporter oboe_settings_t *settings; // cached settings, updated by tracelyzer (init to NULL) int last_auto_sample_rate; // stores last known automatic sampling rate uint16_t last_auto_flags; // stores last known flags associated with above uint32_t last_auto_timestamp; // timestamp from last *settings lookup uint32_t last_refresh; // last refresh time } oboe_settings_cfg_t; int oboe_settings_init_local(); oboe_settings_t* oboe_settings_get(uint16_t type, const char* layer, const char* arg); oboe_settings_t* oboe_settings_get_layer_tracing_mode(const char* layer); oboe_settings_t* oboe_settings_get_layer_sample_rate(const char* layer); oboe_settings_t* oboe_settings_get_layer_app_sample_rate(const char* layer, const char* app); uint32_t oboe_settings_get_latest_timestamp(const char* layer); int oboe_settings_get_value(oboe_settings_t *s, int *outval, unsigned short *outflags, uint32_t *outtimestamp); oboe_settings_cfg_t* oboe_settings_cfg_get(); void oboe_settings_cfg_init(oboe_settings_cfg_t *cfg); void oboe_settings_cfg_tracing_mode_set(int new_mode); void oboe_settings_cfg_sample_rate_set(int new_rate); int oboe_rand_get_value(); /** * Check if sampling is enabled. * * @param cfg Optional pointer to the settings configuration for the current * thread, as an optimization to avoid retrieving it. May be NULL. * @return Non-zero if sampling is now enabled. */ int oboe_sample_is_enabled(oboe_settings_cfg_t *cfg); /** * Check if this request should be sampled (deprecated - use oboe_sample_layer() instead). * * @param layer Layer name as used in oboe_settings_t.layer (may be NULL to use default settings) * @param xtrace X-Trace ID string from an HTTP request or higher layer (NULL or empty string if not present). * @param cfg The settings configuration to use for this evaluation. * @param sample_rate_out The sample rate used to check if this request should be sampled * (output - may be zero if not used). * @param sample_source_out The OBOE_SAMPLE_RATE_SOURCE used to check if this request * should be sampled (output - may be zero if not used). * @return Non-zero if the given layer should be sampled. */ int oboe_sample_request(const char *layer, const char *in_xtrace, oboe_settings_cfg_t *cfg, int *sample_rate_out, int *sample_source_out); /** * Check if this request should be sampled. * * Checks for sample rate flags and settings for the specified layer, considers * the current tracing mode and any special features in the X-Trace and * X-TV-Meta HTTP headers, and, if appropriate, rolls the virtual dice to * decide if this request should be sampled. * * This is designed to be called once per layer per request. * * This replaces oboe_sample_request with a version that uses the settings * configuration kept in thread-local storage and takes the X-TV-Meta HTTP * header value in order to support AppView Web integration. * * @param layer Layer name as used in oboe_settings_t.layer (may be NULL to use default settings) * @param xtrace X-Trace ID string from an HTTP request or higher layer (NULL or empty string if not present). * @param tv_meta AppView Web ID from X-TV-Meta HTTP header or higher layer (NULL or empty string if not present). * @param sample_rate_out The sample rate used to check if this request should be sampled * (output - may be zero if not used). * @param sample_source_out The OBOE_SAMPLE_RATE_SOURCE used to check if this request * should be sampled (output - may be zero if not used). * @return Non-zero if the given layer should be sampled. */ int oboe_sample_layer( const char *layer, const char *xtrace, const char *tv_meta, int *sample_rate_out, int *sample_source_out ); /* Oboe configuration interface. */ /** * Check if the Oboe library is compatible with a given version.revision. * * This will succeed if the library is at least as recent as specified and if no * definitions have been removed since that revision. * * @param version The library's version number which increments every time the API changes. * @param revision The revision of the current version of the library. * @return Non-zero if the Oboe library is considered compatible with the specified revision. */ extern int oboe_config_check_version(int version, int revision); /** * Get the Oboe library version number. * * This number increments whenever the API is changed. * * @return The library's version number or -1 if the version is not known. */ extern int oboe_config_get_version(); /** * Prototype for a logger call-back function. * * A logging function of this form can be added to the logger chain using * oboe_debug_log_add(). * * @param context The context pointer that was registered in the call to * oboe_debug_log_add(). Use it to pass the pointer-to-self for * objects (ie. "this" in C++) or just a structure in C, May be * NULL. * @param module The module identifier as passed to oboe_debug_logger(). * @param level The diagnostic detail level as passed to oboe_debug_logger(). * @param source_name Name of the source file as passed to oboe_debug_logger(). * @param source_lineno Number of the line in the source file where message is * logged from as passed to oboe_debug_logger(). * @param msg The formatted message produced from the format string and its * arguments as passed to oboe_debug_logger(). */ typedef void (*OboeDebugLoggerFcn)(void *context, int module, int level, const char *source_name, int source_lineno, const char *msg); /** * Get a printable name for a diagnostics logging level. */ extern const char *oboe_debug_log_level_name(int level); /** * Get a printable name for a diagnostics logging module identifier. */ extern const char *oboe_debug_module_name(int module); /** * Get the maximum logging detail level for a module or for all modules. * * This level applies to the stderr logger only. Added loggers get all messages * below their registed detail level and need to do their own module-specific * filtering. * * @param module One of the OBOE_MODULE_* values. Use OBOE_MODULE_ALL (-1) to * get the overall maximum detail level. * @return Maximum detail level value for module (or overall) where zero is the * lowest and higher values generate more detailed log messages. */ extern int oboe_debug_log_level_get(int module); /** * Set the maximum logging detail level for a module or for all modules. * * This level applies to the stderr logger only. Added loggers get all messages * below their registed detail level and need to do their own module-specific * filtering. * * @param module One of the OBOE_MODULE_* values. Use OBOE_MODULE_ALL to set * the overall maximum detail level. * @param newLevel Maximum detail level value where zero is the lowest and higher * values generate more detailed log messages. */ extern void oboe_debug_log_level_set(int module, int newLevel); /** * Set the output stream for the default logger. * * @param newStream A valid, open FILE* stream or NULL to disable the default logger. * @return Zero on success; otherwise an error code (normally from errno). */ extern int oboe_debug_log_to_stream(FILE *newStream); /** * Set the default logger to write to the specified file. * * A NULL or empty path name will disable the default logger. * * If the file exists then it will be opened in append mode. * * @param pathname The path name of the * @return Zero on success; otherwise an error code (normally from errno). */ extern int oboe_debug_log_to_file(const char *pathname); /** * Add a logger that takes messages up to a given logging detail level. * * This adds the logger to a chain in order of the logging level. Log messages * are passed to each logger down the chain until the remaining loggers only * accept messages of a lower detail level. * * @return Zero on success, one if re-registered with the new logging level, and * otherwise a negative value to indicate an error. */ extern int oboe_debug_log_add(OboeDebugLoggerFcn newLogger, void *context, int logLevel); /** * Remove a logger. * * Remove the logger from the message handling chain. * * @return Zero on success, one if it was not found, and otherwise a negative * value to indicate an error. */ extern int oboe_debug_log_remove(OboeDebugLoggerFcn oldLogger, void *context); /** * Log a fatal error. */ #if OBOE_DEBUG_LEVEL >= OBOE_DEBUG_FATAL # define OBOE_DEBUG_LOG_FATAL(module, ...) \ { \ oboe_debug_logger(module, OBOE_DEBUG_FATAL, __FILE__, __LINE__, __VA_ARGS__); \ } #else # define OBOE_DEBUG_LOG_FATAL(module, format_string, ...) {} #endif /** * Log a recoverable error. */ #if OBOE_DEBUG_LEVEL >= OBOE_DEBUG_ERROR # define OBOE_DEBUG_LOG_ERROR(module, ...) \ { \ oboe_debug_logger(module, OBOE_DEBUG_ERROR, __FILE__, __LINE__, __VA_ARGS__); \ } #else # define OBOE_DEBUG_LOG_ERROR(module, format_string, ...) {} #endif /** * Log a warning. */ #if OBOE_DEBUG_LEVEL >= OBOE_DEBUG_WARNING # define OBOE_DEBUG_LOG_WARNING(module, ...) \ { \ oboe_debug_logger(module, OBOE_DEBUG_WARNING, __FILE__, __LINE__, __VA_ARGS__); \ } #else # define OBOE_DEBUG_LOG_WARNING(module, format_string,...) {} #endif /** * Log an informative message. */ #if OBOE_DEBUG_LEVEL >= OBOE_DEBUG_INFO # define OBOE_DEBUG_LOG_INFO(module, ...) \ { \ oboe_debug_logger(module, OBOE_DEBUG_INFO, __FILE__, __LINE__, __VA_ARGS__); \ } #else # define OBOE_DEBUG_LOG_INFO(module, format_string, ...) {} #endif /** * Log a low-detail diagnostic message. */ #if OBOE_DEBUG_LEVEL >= OBOE_DEBUG_LOW # define OBOE_DEBUG_LOG_LOW(module, ...) \ { \ oboe_debug_logger(module, OBOE_DEBUG_LOW, __FILE__, __LINE__, __VA_ARGS__); \ } #else # define OBOE_DEBUG_LOG_LOW(module, format_string, ...) {} #endif /** * Log a medium-detail diagnostic message. */ #if OBOE_DEBUG_LEVEL >= OBOE_DEBUG_MEDIUM # define OBOE_DEBUG_LOG_MEDIUM(module, ...) \ { \ oboe_debug_logger(module, OBOE_DEBUG_MEDIUM, __FILE__, __LINE__, __VA_ARGS__); \ } #else # define OBOE_DEBUG_LOG_MEDIUM(module, ...) {} #endif /** * Log a high-detail diagnostic message. */ #if OBOE_DEBUG_LEVEL >= OBOE_DEBUG_HIGH # define OBOE_DEBUG_LOG_HIGH(module, ...) \ { \ oboe_debug_logger(module, OBOE_DEBUG_HIGH, __FILE__, __LINE__, __VA_ARGS__); \ } #else # define OBOE_DEBUG_LOG_HIGH(module, format_string, ...) {} #endif /** * Low-level diagnostics logging function. * * This is normally used only by the OBOE_DEBUG_LOG_* function macros and not used directly. * * This function may be adapted to format and route diagnostic log messages as desired. * * @param module One of the numeric module identifiers defined in debug.h - used to control logging detail by module. * @param level Diagnostic detail level of this message - used to control logging volume by detail level. * @param source_name Name of the source file, if available, or another useful name, or NULL. * @param source_lineno Number of the line in the source file where message is logged from, if available, or zero. * @param format A C language printf format specification string. * @param args A variable argument list in VA_ARG format containing arguments for each argument specifier in the format. */ void oboe_debug_logger(int module, int level, const char *source_name, int source_lineno, const char *format, ...); /** * Get the Oboe library revision number. * * This is the revision of the current version which is updated whenever * compatible changes are made to the API/ABI (ie. additions). * * @return The library's revision number or -1 if not known. */ extern int oboe_config_get_revision(); /* * Get the Oboe library version as a string. * * Returns the complete VERSION string or null */ const char* oboe_config_get_version_string(); #ifdef __cplusplus } // extern "C" #endif #endif // LIBOBOE_H