/* \brief 应用状态监测数据输出 * * \author Lu Qiuwen * \date 2016-11-30 */ #include #include unsigned int g_monit_interval = 1; int vdev_instance_stats_get(struct vdev_instance * vdi, struct vdev_stat_info * stat_info) { struct vnode_cons_stat * st_cons_rx = NULL; struct vnode_prod_stat * st_prod_tx = NULL; struct vnode_prod_stat * st_prod_ftx = NULL; struct vnode_prod_stat * st_prod_ltx = NULL; if(vdi->nr_rxstream > 0) { st_cons_rx = vnode_mirror_cons_stat_get(vdi->vnode_rx_cons); } if(vdi->nr_txstream > 0) { st_prod_tx = vnode_mirror_prod_stat_get(vdi->vnode_tx_prod); st_prod_ftx = vnode_mirror_prod_stat_get(vdi->vnode_ftx_prod); st_prod_ltx = vnode_mirror_prod_stat_get(vdi->vnode_ltx_prod); } stat_info->nr_rxstream = vdi->nr_rxstream; stat_info->nr_txstream = vdi->nr_txstream; for (int i = 0; i < vdi->nr_rxstream; i++) { stat_info->rx_on_line[i] = VNODE_STAT_READ(&st_cons_rx[i].on_line); stat_info->rx_deliver[i] = VNODE_STAT_READ(&st_cons_rx[i].deliver); stat_info->rx_missed[i] = VNODE_STAT_READ(&st_cons_rx[i].missed); stat_info->rx_total_len[i] = VNODE_STAT_READ(&st_cons_rx[i].total_len); } for (int i = 0; i < vdi->nr_txstream; i++) { stat_info->tx_on_line[i] = VNODE_STAT_READ(&st_prod_tx[i].on_line); stat_info->tx_deliver[i] = VNODE_STAT_READ(&st_prod_tx[i].deliver); stat_info->tx_missed[i] = VNODE_STAT_READ(&st_prod_tx[i].missed); stat_info->tx_total_len[i] = VNODE_STAT_READ(&st_prod_tx[i].total_len); stat_info->ftx_on_line[i] = VNODE_STAT_READ(&st_prod_ftx[i].on_line); stat_info->ftx_deliver[i] = VNODE_STAT_READ(&st_prod_ftx[i].deliver); stat_info->ftx_missed[i] = VNODE_STAT_READ(&st_prod_ftx[i].missed); stat_info->ftx_total_len[i] = VNODE_STAT_READ(&st_prod_ftx[i].total_len); stat_info->ltx_on_line[i] = VNODE_STAT_READ(&st_prod_ltx[i].on_line); stat_info->ltx_deliver[i] = VNODE_STAT_READ(&st_prod_ltx[i].deliver); stat_info->ltx_missed[i] = VNODE_STAT_READ(&st_prod_ltx[i].missed); stat_info->ltx_total_len[i] = VNODE_STAT_READ(&st_prod_ltx[i].total_len); } return 0; } void vdev_instance_stat_last_save(struct vdev_instance * vdi, struct vdev_stat_info * stat_info) { vdi->stat_info_last = *stat_info; } void vdev_instance_stats_last_get(struct vdev_instance * vdi, struct vdev_stat_info * stat_info) { *stat_info = vdi->stat_info_last; } static cJSON * __create_uint64_array(const uint64_t * value, int nr_value) { struct cJSON * uint64_array = cJSON_CreateArray(); for (int i = 0; i < nr_value; i++) cJSON_AddItemToArray(uint64_array, cJSON_CreateNumber(value[i])); return uint64_array; } static cJSON * __create_uint64_delta_array(const uint64_t * value_large, const uint64_t * value_small, int nr_value, int interval) { struct cJSON * uint64_array = cJSON_CreateArray(); for (int i = 0; i < nr_value; i++) { uint64_t delta = (value_large[i] - value_small[i]) / interval; cJSON_AddItemToArray(uint64_array, cJSON_CreateNumber(delta)); } return uint64_array; } static cJSON * __create_vdev_stats(struct vdev_instance * vdi) { struct vdev_stat_info _stat_info; struct vdev_stat_info _stat_info_last; vdev_instance_stats_get(vdi, &_stat_info); vdev_instance_stats_last_get(vdi, &_stat_info_last); vdev_instance_stat_last_save(vdi, &_stat_info); unsigned int nr_rx_stream = _stat_info.nr_rxstream; unsigned int nr_tx_stream = _stat_info.nr_txstream; /* 统计节点句柄 */ struct cJSON * j_vdev_stats = cJSON_CreateObject(); /* 累计量 */ struct cJSON * j_vdev_value = cJSON_CreateObject(); /* 瞬时值 */ struct cJSON * j_vdev_speed = cJSON_CreateObject(); #define __JOIN_VDEV_VALUE_STATS_ITEM(item, streams) do { \ cJSON_AddItemToObject(j_vdev_value, #item, \ __create_uint64_array(_stat_info.item, streams)); \ } while(0) #define __JOIN_VDEV_VALUE_BYTES_TO_BITS_STAT_ITEM(item, streams) do { \ uint64_t __bits_item[MR_SID_MAX]; \ for (int i = 0; i < streams; i++) \ __bits_item[i] = _stat_info.item[i] * 8; \ \ cJSON_AddItemToObject(j_vdev_value, #item, __create_uint64_array( \ __bits_item, streams)); \ } while(0) __JOIN_VDEV_VALUE_STATS_ITEM(rx_on_line, nr_rx_stream); __JOIN_VDEV_VALUE_STATS_ITEM(rx_deliver, nr_rx_stream); __JOIN_VDEV_VALUE_STATS_ITEM(rx_missed, nr_rx_stream); __JOIN_VDEV_VALUE_BYTES_TO_BITS_STAT_ITEM(rx_total_len, nr_rx_stream); __JOIN_VDEV_VALUE_STATS_ITEM(tx_on_line, nr_tx_stream); __JOIN_VDEV_VALUE_STATS_ITEM(tx_deliver, nr_tx_stream); __JOIN_VDEV_VALUE_STATS_ITEM(tx_missed, nr_tx_stream); __JOIN_VDEV_VALUE_BYTES_TO_BITS_STAT_ITEM(tx_total_len, nr_tx_stream); __JOIN_VDEV_VALUE_STATS_ITEM(ftx_on_line, nr_tx_stream); __JOIN_VDEV_VALUE_STATS_ITEM(ftx_deliver, nr_tx_stream); __JOIN_VDEV_VALUE_STATS_ITEM(ftx_missed, nr_tx_stream); __JOIN_VDEV_VALUE_BYTES_TO_BITS_STAT_ITEM(ftx_total_len, nr_tx_stream); __JOIN_VDEV_VALUE_STATS_ITEM(ltx_on_line, nr_tx_stream); __JOIN_VDEV_VALUE_STATS_ITEM(ltx_deliver, nr_tx_stream); __JOIN_VDEV_VALUE_STATS_ITEM(ltx_missed, nr_tx_stream); __JOIN_VDEV_VALUE_BYTES_TO_BITS_STAT_ITEM(ltx_total_len, nr_tx_stream); #define __JOIN_VDEV_SPEED_STATS_ITEM(item, streams) do { \ cJSON_AddItemToObject(j_vdev_speed, #item, \ __create_uint64_delta_array(_stat_info.item, \ _stat_info_last.item, streams, g_monit_interval)); \ } while(0) #define __JOIN_VDEV_SPEED_BYTES_TO_BITS_STAT_ITEM(item, streams) do { \ uint64_t __bits_item[MR_SID_MAX]; \ for (int i = 0; i < streams; i++) \ __bits_item[i] = _stat_info.item[i] * 8; \ \ uint64_t __bits_item_last[MR_SID_MAX]; \ for (int i = 0; i < streams; i++) \ __bits_item_last[i] = _stat_info_last.item[i] * 8; \ \ cJSON_AddItemToObject(j_vdev_speed, #item, \ __create_uint64_delta_array(__bits_item, \ __bits_item_last, streams, g_monit_interval)); \ } while(0) __JOIN_VDEV_SPEED_STATS_ITEM(rx_on_line, nr_rx_stream); __JOIN_VDEV_SPEED_STATS_ITEM(rx_deliver, nr_rx_stream); __JOIN_VDEV_SPEED_STATS_ITEM(rx_missed, nr_rx_stream); __JOIN_VDEV_SPEED_BYTES_TO_BITS_STAT_ITEM(rx_total_len, nr_rx_stream); __JOIN_VDEV_SPEED_STATS_ITEM(tx_on_line, nr_tx_stream); __JOIN_VDEV_SPEED_STATS_ITEM(tx_deliver, nr_tx_stream); __JOIN_VDEV_SPEED_STATS_ITEM(tx_missed, nr_tx_stream); __JOIN_VDEV_SPEED_BYTES_TO_BITS_STAT_ITEM(tx_total_len, nr_tx_stream); __JOIN_VDEV_SPEED_STATS_ITEM(ftx_on_line, nr_tx_stream); __JOIN_VDEV_SPEED_STATS_ITEM(ftx_deliver, nr_tx_stream); __JOIN_VDEV_SPEED_STATS_ITEM(ftx_missed, nr_tx_stream); __JOIN_VDEV_SPEED_BYTES_TO_BITS_STAT_ITEM(ftx_total_len, nr_tx_stream); __JOIN_VDEV_SPEED_STATS_ITEM(ltx_on_line, nr_tx_stream); __JOIN_VDEV_SPEED_STATS_ITEM(ltx_deliver, nr_tx_stream); __JOIN_VDEV_SPEED_STATS_ITEM(ltx_missed, nr_tx_stream); __JOIN_VDEV_SPEED_BYTES_TO_BITS_STAT_ITEM(ltx_total_len, nr_tx_stream); cJSON_AddItemToObject(j_vdev_stats, "accumulative", j_vdev_value); cJSON_AddItemToObject(j_vdev_stats, "speed", j_vdev_speed); return j_vdev_stats; } // 运行时原始报文设备统计计数 static cJSON * monit_vdev(struct mr_instance * instance) { struct cJSON * j_vdev_array = cJSON_CreateArray(); for(int i = 0; i < instance->nr_vdevs; i++) { struct mr_vdev * vdev = &instance->vdevs[i]; if (vdev == NULL) continue; cJSON * j_vdev = cJSON_CreateObject(); cJSON_AddStringToObject(j_vdev, "symbol", vdev->devsym); cJSON_AddNumberToObject(j_vdev, "rxstreams", vdev->nr_rxstream); cJSON_AddNumberToObject(j_vdev, "txstreams", vdev->nr_txstream); cJSON_AddItemToObject(j_vdev, "stats", __create_vdev_stats(vdev->vdi)); cJSON_AddItemToArray(j_vdev_array, j_vdev); } return j_vdev_array; } static cJSON * monit_app_stat(struct mr_instance * instance) { struct cJSON * j_root = cJSON_CreateObject(); #define _trans_app_stat(item) \ uint64_t __trans_##item[MR_SID_MAX]; \ for(int i = 0; i < instance->nr_dataplane_thread; i++) \ { \ __trans_##item[i] = instance->stat[i].item; \ } \ #define _trans_app_stat_array(item) __trans_##item _trans_app_stat(packet_recv_count); _trans_app_stat(packet_recv_length); _trans_app_stat(packet_send_count); _trans_app_stat(packet_send_length); _trans_app_stat(packet_recv_drop); _trans_app_stat(packet_send_drop); _trans_app_stat(mbuf_alloc_count); _trans_app_stat(mbuf_free_count); _trans_app_stat(poll_wake_up_by_ev); _trans_app_stat(poll_wake_up_timeout); /* 在用Buffer数量统计 */ uint64_t __trans_mbuf_in_use_count[MR_SID_MAX]; for (int i = 0; i < instance->nr_dataplane_thread; i++) { __trans_mbuf_in_use_count[i] = __trans_packet_recv_count[i] + __trans_mbuf_alloc_count[i] - __trans_packet_send_count[i] - __trans_mbuf_free_count[i]; } #define _json_generate(item) \ do { \ cJSON_AddItemToObject(j_root, #item, __create_uint64_array( \ _trans_app_stat_array(item), instance->nr_dataplane_thread)); \ } while(0) \ _json_generate(packet_recv_count); _json_generate(packet_recv_length); _json_generate(packet_send_count); _json_generate(packet_send_length); _json_generate(packet_recv_drop); _json_generate(packet_send_drop); _json_generate(mbuf_alloc_count); _json_generate(mbuf_free_count); _json_generate(mbuf_in_use_count); _json_generate(poll_wake_up_by_ev); _json_generate(poll_wake_up_timeout); #undef _trans_app_stat #undef _trans_app_stat_array #undef _json_generate return j_root; } static cJSON * monit_app_info(struct mr_instance * instance) { struct cJSON * j_root = cJSON_CreateObject(); cJSON_AddStringToObject(j_root, "symbol", instance->appsym); return j_root; } static cJSON * monit_root(struct mr_instance * instance) { struct cJSON * j_root = cJSON_CreateObject(); cJSON_AddItemToObject(j_root, "appinfo", monit_app_info(instance)); cJSON_AddItemToObject(j_root, "raw", monit_vdev(instance)); cJSON_AddItemToObject(j_root, "appstat", monit_app_stat(instance)); if (instance->neigh != NULL) { struct cJSON * j_monit_neigh = neighbour_manager_monit(instance->neigh); cJSON_AddItemToObject(j_root, "neigh", j_monit_neigh); } return j_root; } int mrapp_monit_loop(struct mr_instance * instance) { cJSON * j_root = monit_root(instance); char * str_json_print = cJSON_Print(j_root); FILE * fp_monit = fopen(instance->monit_file_path, "w"); if (fp_monit == NULL) { MR_WARNING("monit file %s open failed, cannot dump program stat info : %s", instance->monit_file_path, strerror(errno)); return 0; } fprintf(fp_monit, "%s", str_json_print); cJSON_Delete(j_root); free(str_json_print); fclose(fp_monit); return 0; }