/** * Copyright (C) Mellanox Technologies Ltd. 2001-2013. ALL RIGHTS RESERVED. * * See file LICENSE for terms. */ #ifndef UCS_LIBSTATS_H_ #define UCS_LIBSTATS_H_ #include #include #include #include #include #include #include /* * Serialization options */ enum { UCS_STATS_SERIALIZE_INACTVIVE = UCS_BIT(0), /* Use "inactive" tree */ UCS_STATS_SERIALIZE_BINARY = UCS_BIT(1), /* Binary mode */ UCS_STATS_SERIALIZE_COMPRESS = UCS_BIT(2) /* Compress */ }; #define UCS_STATS_DEFAULT_UDP_PORT 37873 #define UCS_STAT_NAME_MAX 39 #define UCS_STATS_NODE_FMT \ "%s%s" #define UCS_STATS_NODE_ARG(_node) \ (_node)->cls->name, (_node)->name #define UCS_STATS_INDENT(_is_sum, _indent) _is_sum ? 0 : (_indent) * 2, "" #define UCS_STATS_IS_LAST_COUNTER(_counters_bits, _current) \ (_counters_bits > ((2ull<<_current) - 1)) typedef struct ucs_stats_server *ucs_stats_server_h; /* Handle to server */ typedef struct ucs_stats_client *ucs_stats_client_h; /* Handle to client */ typedef enum ucs_stats_children_sel { UCS_STATS_INACTIVE_CHILDREN, UCS_STATS_ACTIVE_CHILDREN, UCS_STATS_CHILDREN_LAST } ucs_stats_children_sel_t; /* Statistics class */ struct ucs_stats_class { const char *name; unsigned num_counters; const char* counter_names[]; }; /* * ucs_stats_node is used to hold the counters, their classes and the * relationship between them. * ucs_stats_filter_node is a data structure used to filter the counters * on the report. * Therre are 3 types of filtering: Full, Aggregate, and summary * Following is an example of the data structures in aggregate mode: * * ucs_stats_node ucs_stats_filter_node * -------------- --------------------- * * +-----+ +-----+ * | A-1 |............................> | A-1 | * +-----+ +-----+ * A A A A * | | | | * | | +----------+ | * | | | | * +--+ +--+ +--+--+................. | * | | | B-1 | : | * | | +-----+ : | * | +-----+....|..A................. : | * | | B-2 | | | : : | * | +-----+ <--+ | V V | * +-----+......|..........|.............> +-----+ * | B-3 | || +---------------| B* | * +-----+ <----+ +-----+ * cntr1 cntr1* * cntr2 cntr2* * cntr3 cntr3* * * unfiltered statistics report: * * A-1: * B-1: * cntr1: 11111 * cntr2: 22222 * cntr3: 33333 * B-2: * cntr1: 11111 * cntr2: 22222 * cntr3: 33333 * B-3: * cntr1: 11111 * cntr2: 22222 * cntr3: 33333 * * filtered statistics report: * * A-1: * B*: * cntr1: 33333 * cntr2: 66666 * cntr3: 99999 * */ /* In-memory statistics node */ struct ucs_stats_node { ucs_stats_class_t *cls; /* Class info */ ucs_stats_node_t *parent; /* Hierachy structure */ char name[UCS_STAT_NAME_MAX + 1]; /* instance name */ ucs_list_link_t list; /* nodes sharing same parent */ ucs_list_link_t children[UCS_STATS_CHILDREN_LAST]; /* children list head */ ucs_list_link_t type_list; /* nodes with same class/es hierarchy */ ucs_stats_filter_node_t *filter_node; /* ptr to type list head */ ucs_stats_counter_t counters[1]; /* instance counters */ }; struct ucs_stats_filter_node { ucs_stats_filter_node_t *parent; ucs_list_link_t list; /* nodes sharing same parent.*/ ucs_list_link_t children; ucs_list_link_t type_list_head; /* nodes with same ancestors classes */ int type_list_len; /* length of list */ int ref_count; /* report node when non zero */ uint64_t counters_bitmask; /* which counters to print */ }; /** * Initialize statistics node. * * @param node Node to initialize. * @param cls Node class. * @param name Node name format string. * @param ap Name formatting arguments. */ ucs_status_t ucs_stats_node_initv(ucs_stats_node_t *node, ucs_stats_class_t *cls, const char *name, va_list ap); /** * Serialize statistics. * * @param stream Destination * @param root Statistics node root. * @param options Serialization options. */ ucs_status_t ucs_stats_serialize(FILE *stream, ucs_stats_node_t *root, int options); /** * De-serialize statistics. * * @param stream Source data. * @param p_roo Filled with tatistics node root. * * @return UCS_ERR_NO_ELEM if hit EOF. */ ucs_status_t ucs_stats_deserialize(FILE *stream, ucs_stats_node_t **p_root); /** * Release stats returned by ucs_stats_deserialize(). * @param root Stats to release. */ void ucs_stats_free(ucs_stats_node_t *root); /** * Initialize statistics client. * * @param server_addr Address of server machine. * @param port Port number on server. * @param p_client Filled with handle to the client. */ ucs_status_t ucs_stats_client_init(const char *server_addr, int port, ucs_stats_client_h *p_client); /** * Destroy statistics client. */ void ucs_stats_client_cleanup(ucs_stats_client_h client); /** * Send statistics. * * @param client Client handle. * @param root Statistics tree root. * @param timestamp Current statistics timestamp, identifies every "snapshot". */ ucs_status_t ucs_stats_client_send(ucs_stats_client_h client, ucs_stats_node_t *root, uint64_t timestamp); /** * Start a thread running a server which receives statistics. * * @param port Port number to listen on. 0 - random available port. * @param verbose Verbose level. * @param p_server Filled with handle to the server. */ ucs_status_t ucs_stats_server_start(int port, ucs_stats_server_h *p_server); /** * Stop statistics server. * @param server Handle to statistics server. */ void ucs_stats_server_destroy(ucs_stats_server_h server); /** * Get port number used by the server, useful if we started it on a random port. * * @param server Handle to statistics server. * * @return Port number. */ int ucs_stats_server_get_port(ucs_stats_server_h server); /** * Get current statistics gathered by the server. The data is valid until the next * call to any of the following functions: * - ucs_stats_server_purge_stats * - ucs_stats_server_cleanup * - ucs_stats_server_get_stats * * @param server Handle to statistics server. * @return A list of stat trees for all entities gathered by the server. */ ucs_list_link_t *ucs_stats_server_get_stats(ucs_stats_server_h server); /** * Clean up existing statistics. */ void ucs_stats_server_purge_stats(ucs_stats_server_h server); /** * @return Number of packets received by the server. */ unsigned long ucs_stats_server_rcvd_packets(ucs_stats_server_h server); #endif /* LIBSTATS_H_ */