2024-06-25 14:08:33 +08:00
|
|
|
#include <errno.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#include "log.h"
|
|
|
|
|
#include "stellar_stat.h"
|
|
|
|
|
#include "fieldstat/fieldstat_easy.h"
|
|
|
|
|
#include "fieldstat/fieldstat_exporter.h"
|
|
|
|
|
|
|
|
|
|
#define STAT_LOG_ERROR(format, ...) LOG_ERROR("stat", format, ##__VA_ARGS__)
|
|
|
|
|
|
|
|
|
|
#define IS_FREE 0
|
|
|
|
|
#define IS_BUSY 0xf
|
|
|
|
|
|
|
|
|
|
typedef uint64_t get_val_func(struct thread_stat *thr_stat);
|
2024-08-16 17:44:23 +08:00
|
|
|
static inline uint64_t get_pkts_rx(struct thread_stat *thr_stat) { return thr_stat->packet_io->pkts_rx; }
|
|
|
|
|
static inline uint64_t get_bytes_rx(struct thread_stat *thr_stat) { return thr_stat->packet_io->bytes_rx; }
|
|
|
|
|
static inline uint64_t get_pkts_tx(struct thread_stat *thr_stat) { return thr_stat->packet_io->pkts_tx; }
|
|
|
|
|
static inline uint64_t get_bytes_tx(struct thread_stat *thr_stat) { return thr_stat->packet_io->bytes_tx; }
|
2024-06-25 14:08:33 +08:00
|
|
|
static inline uint64_t get_keep_alive_pkts(struct thread_stat *thr_stat) { return thr_stat->packet_io->keep_alive_pkts; }
|
|
|
|
|
static inline uint64_t get_keep_alive_bytes(struct thread_stat *thr_stat) { return thr_stat->packet_io->keep_alive_bytes; }
|
2024-08-16 17:44:23 +08:00
|
|
|
static inline uint64_t get_raw_pkts_rx(struct thread_stat *thr_stat) { return thr_stat->packet_io->raw_pkts_rx; }
|
|
|
|
|
static inline uint64_t get_raw_bytes_rx(struct thread_stat *thr_stat) { return thr_stat->packet_io->raw_bytes_rx; }
|
|
|
|
|
static inline uint64_t get_raw_pkts_tx(struct thread_stat *thr_stat) { return thr_stat->packet_io->raw_pkts_tx; }
|
|
|
|
|
static inline uint64_t get_raw_bytes_tx(struct thread_stat *thr_stat) { return thr_stat->packet_io->raw_bytes_tx; }
|
|
|
|
|
static inline uint64_t get_pkts_dropped(struct thread_stat *thr_stat) { return thr_stat->packet_io->pkts_dropped; }
|
|
|
|
|
static inline uint64_t get_bytes_dropped(struct thread_stat *thr_stat) { return thr_stat->packet_io->bytes_dropped; }
|
|
|
|
|
static inline uint64_t get_pkts_injected(struct thread_stat *thr_stat) { return thr_stat->packet_io->pkts_injected; }
|
|
|
|
|
static inline uint64_t get_bytes_injected(struct thread_stat *thr_stat) { return thr_stat->packet_io->bytes_injected; }
|
|
|
|
|
static inline uint64_t get_ctrl_pkts_rx(struct thread_stat *thr_stat) { return thr_stat->packet_io->ctrl_pkts_rx; }
|
|
|
|
|
static inline uint64_t get_ctrl_bytes_rx(struct thread_stat *thr_stat) { return thr_stat->packet_io->ctrl_bytes_rx; }
|
|
|
|
|
static inline uint64_t get_ctrl_pkts_tx(struct thread_stat *thr_stat) { return thr_stat->packet_io->ctrl_pkts_tx; }
|
|
|
|
|
static inline uint64_t get_ctrl_bytes_tx(struct thread_stat *thr_stat) { return thr_stat->packet_io->ctrl_bytes_tx; }
|
2024-06-25 14:08:33 +08:00
|
|
|
static inline uint64_t get_ip4_flow_find(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip4_flow_find; }
|
|
|
|
|
static inline uint64_t get_ip4_flow_add(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip4_flow_add; }
|
|
|
|
|
static inline uint64_t get_ip4_flow_del(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip4_flow_del; }
|
|
|
|
|
static inline uint64_t get_ip4_flow_timeout(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip4_flow_timeout; }
|
|
|
|
|
static inline uint64_t get_ip4_flow_fail_no_space(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip4_flow_fail_no_space; }
|
|
|
|
|
static inline uint64_t get_ip4_flow_fail_overlap(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip4_flow_fail_overlap; }
|
|
|
|
|
static inline uint64_t get_ip4_flow_fail_many_frag(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip4_flow_fail_many_frag; }
|
|
|
|
|
static inline uint64_t get_ip4_flow_fail_invalid_length(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip4_flow_fail_invalid_length; }
|
|
|
|
|
static inline uint64_t get_ip4_flow_bypass_dup_fist_frag(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip4_flow_bypass_dup_fist_frag; }
|
|
|
|
|
static inline uint64_t get_ip4_flow_bypass_dup_last_frag(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip4_flow_bypass_dup_last_frag; }
|
|
|
|
|
static inline uint64_t get_ip6_flow_find(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip6_flow_find; }
|
|
|
|
|
static inline uint64_t get_ip6_flow_add(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip6_flow_add; }
|
|
|
|
|
static inline uint64_t get_ip6_flow_del(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip6_flow_del; }
|
|
|
|
|
static inline uint64_t get_ip6_flow_timeout(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip6_flow_timeout; }
|
|
|
|
|
static inline uint64_t get_ip6_flow_fail_no_space(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip6_flow_fail_no_space; }
|
|
|
|
|
static inline uint64_t get_ip6_flow_fail_overlap(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip6_flow_fail_overlap; }
|
|
|
|
|
static inline uint64_t get_ip6_flow_fail_many_frag(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip6_flow_fail_many_frag; }
|
|
|
|
|
static inline uint64_t get_ip6_flow_fail_invalid_length(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip6_flow_fail_invalid_length; }
|
|
|
|
|
static inline uint64_t get_ip6_flow_bypass_dup_fist_frag(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip6_flow_bypass_dup_fist_frag; }
|
|
|
|
|
static inline uint64_t get_ip6_flow_bypass_dup_last_frag(struct thread_stat *thr_stat) { return thr_stat->ip_reassembly->ip6_flow_bypass_dup_last_frag; }
|
2024-08-14 11:25:04 +08:00
|
|
|
static inline uint64_t get_total_tcp_sess_used(struct thread_stat *thr_stat) { return thr_stat->session_mgr->total_tcp_sess_used; }
|
|
|
|
|
static inline uint64_t get_curr_tcp_sess_used(struct thread_stat *thr_stat) { return thr_stat->session_mgr->curr_tcp_sess_used; }
|
|
|
|
|
static inline uint64_t get_curr_tcp_sess_opening(struct thread_stat *thr_stat) { return thr_stat->session_mgr->curr_tcp_sess_opening; }
|
|
|
|
|
static inline uint64_t get_curr_tcp_sess_active(struct thread_stat *thr_stat) { return thr_stat->session_mgr->curr_tcp_sess_active; }
|
|
|
|
|
static inline uint64_t get_curr_tcp_sess_closing(struct thread_stat *thr_stat) { return thr_stat->session_mgr->curr_tcp_sess_closing; }
|
|
|
|
|
static inline uint64_t get_curr_tcp_sess_discard(struct thread_stat *thr_stat) { return thr_stat->session_mgr->curr_tcp_sess_discard; }
|
|
|
|
|
static inline uint64_t get_curr_tcp_sess_closed(struct thread_stat *thr_stat) { return thr_stat->session_mgr->curr_tcp_sess_closed; }
|
|
|
|
|
static inline uint64_t get_total_udp_sess_used(struct thread_stat *thr_stat) { return thr_stat->session_mgr->total_udp_sess_used; }
|
|
|
|
|
static inline uint64_t get_curr_udp_sess_used(struct thread_stat *thr_stat) { return thr_stat->session_mgr->curr_udp_sess_used; }
|
|
|
|
|
static inline uint64_t get_curr_udp_sess_opening(struct thread_stat *thr_stat) { return thr_stat->session_mgr->curr_udp_sess_opening; }
|
|
|
|
|
static inline uint64_t get_curr_udp_sess_active(struct thread_stat *thr_stat) { return thr_stat->session_mgr->curr_udp_sess_active; }
|
|
|
|
|
static inline uint64_t get_curr_udp_sess_closing(struct thread_stat *thr_stat) { return thr_stat->session_mgr->curr_udp_sess_closing; }
|
|
|
|
|
static inline uint64_t get_curr_udp_sess_discard(struct thread_stat *thr_stat) { return thr_stat->session_mgr->curr_udp_sess_discard; }
|
|
|
|
|
static inline uint64_t get_curr_udp_sess_closed(struct thread_stat *thr_stat) { return thr_stat->session_mgr->curr_udp_sess_closed; }
|
|
|
|
|
static inline uint64_t get_tcp_sess_evicted(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_sess_evicted; }
|
|
|
|
|
static inline uint64_t get_udp_sess_evicted(struct thread_stat *thr_stat) { return thr_stat->session_mgr->udp_sess_evicted; }
|
2024-08-16 18:32:35 +08:00
|
|
|
static inline uint64_t get_udp_pkts_bypass_table_full(struct thread_stat *thr_stat) { return thr_stat->session_mgr->udp_pkts_bypass_table_full; }
|
|
|
|
|
static inline uint64_t get_tcp_pkts_bypass_table_full(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_pkts_bypass_table_full; }
|
|
|
|
|
static inline uint64_t get_tcp_pkts_bypass_session_not_found(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_pkts_bypass_session_not_found; }
|
|
|
|
|
static inline uint64_t get_tcp_pkts_bypass_duplicated(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_pkts_bypass_duplicated; }
|
|
|
|
|
static inline uint64_t get_udp_pkts_bypass_duplicated(struct thread_stat *thr_stat) { return thr_stat->session_mgr->udp_pkts_bypass_duplicated; }
|
|
|
|
|
static inline uint64_t get_udp_pkts_bypass_session_evicted(struct thread_stat *thr_stat) { return thr_stat->session_mgr->udp_pkts_bypass_session_evicted; }
|
2024-08-16 18:24:54 +08:00
|
|
|
static inline uint64_t get_tcp_segs_input(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_segs_input; }
|
|
|
|
|
static inline uint64_t get_tcp_segs_timeout(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_segs_timeout; }
|
|
|
|
|
static inline uint64_t get_tcp_segs_retransmited(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_segs_retransmited; }
|
|
|
|
|
static inline uint64_t get_tcp_segs_overlapped(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_segs_overlapped; }
|
|
|
|
|
static inline uint64_t get_tcp_segs_omitted_too_many(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_segs_omitted_too_many; }
|
|
|
|
|
static inline uint64_t get_tcp_segs_inorder(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_segs_inorder; }
|
|
|
|
|
static inline uint64_t get_tcp_segs_reordered(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_segs_reordered; }
|
|
|
|
|
static inline uint64_t get_tcp_segs_buffered(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_segs_buffered; }
|
|
|
|
|
static inline uint64_t get_tcp_segs_freed(struct thread_stat *thr_stat) { return thr_stat->session_mgr->tcp_segs_freed; }
|
2024-06-25 14:08:33 +08:00
|
|
|
|
2024-08-16 17:44:23 +08:00
|
|
|
/*
|
|
|
|
|
* This naming convention maintains consistency by using a clear, structured pattern:
|
|
|
|
|
* • tcp_sessions_ or ipv6_frags_ as the prefix to indicate the type of data.
|
|
|
|
|
* • Action or status (e.g., bypassed, active, dropped) as the middle part.
|
|
|
|
|
* • Cause or condition (e.g., full_table, buffer_limit) as the suffix for additional clarity.
|
|
|
|
|
*/
|
2024-06-25 14:08:33 +08:00
|
|
|
struct metric_schema
|
|
|
|
|
{
|
|
|
|
|
const char *name;
|
|
|
|
|
get_val_func *get_val;
|
|
|
|
|
} schemas[] =
|
|
|
|
|
{
|
|
|
|
|
// device packet
|
2024-08-16 17:44:23 +08:00
|
|
|
{"pkts_rx", get_pkts_rx},
|
|
|
|
|
{"bytes_rx", get_bytes_rx},
|
|
|
|
|
{"pkts_tx", get_pkts_tx},
|
|
|
|
|
{"bytes_tx", get_bytes_tx},
|
2024-06-25 14:08:33 +08:00
|
|
|
// keep-alive packet
|
|
|
|
|
{"keep_alive_pkts", get_keep_alive_pkts},
|
|
|
|
|
{"keep_alive_bytes", get_keep_alive_bytes},
|
|
|
|
|
// raw packet
|
2024-08-16 17:44:23 +08:00
|
|
|
{"raw_pkts_rx", get_raw_pkts_rx},
|
|
|
|
|
{"raw_bytes_rx", get_raw_bytes_rx},
|
|
|
|
|
{"raw_pkts_tx", get_raw_pkts_tx},
|
|
|
|
|
{"raw_bytes_tx", get_raw_bytes_tx},
|
2024-06-25 14:08:33 +08:00
|
|
|
// drop packet
|
2024-08-16 17:44:23 +08:00
|
|
|
{"pkts_dropped", get_pkts_dropped},
|
|
|
|
|
{"bytes_dropped", get_bytes_dropped},
|
2024-06-25 14:08:33 +08:00
|
|
|
// inject packet
|
2024-08-16 17:44:23 +08:00
|
|
|
{"pkts_injected", get_pkts_injected},
|
|
|
|
|
{"bytes_injected", get_bytes_injected},
|
2024-06-25 14:08:33 +08:00
|
|
|
// ctrl packet
|
2024-08-16 17:44:23 +08:00
|
|
|
{"ctrl_pkts_rx", get_ctrl_pkts_rx},
|
|
|
|
|
{"ctrl_bytes_rx", get_ctrl_bytes_rx},
|
|
|
|
|
{"ctrl_pkts_tx", get_ctrl_pkts_tx},
|
|
|
|
|
{"ctrl_bytes_tx", get_ctrl_bytes_tx},
|
2024-06-25 14:08:33 +08:00
|
|
|
// ipv4 reassembly
|
|
|
|
|
{"ip4_flow_find", get_ip4_flow_find},
|
|
|
|
|
{"ip4_flow_add", get_ip4_flow_add},
|
|
|
|
|
{"ip4_flow_del", get_ip4_flow_del},
|
|
|
|
|
{"ip4_flow_timeout", get_ip4_flow_timeout},
|
|
|
|
|
{"ip4_flow_fail_no_space", get_ip4_flow_fail_no_space},
|
|
|
|
|
{"ip4_flow_fail_overlap", get_ip4_flow_fail_overlap},
|
|
|
|
|
{"ip4_flow_fail_many_frag", get_ip4_flow_fail_many_frag},
|
|
|
|
|
{"ip4_flow_fail_invalid_length", get_ip4_flow_fail_invalid_length},
|
|
|
|
|
{"ip4_flow_bypass_dup_fist_frag", get_ip4_flow_bypass_dup_fist_frag},
|
|
|
|
|
{"ip4_flow_bypass_dup_last_frag", get_ip4_flow_bypass_dup_last_frag},
|
|
|
|
|
// ipv6 reassembly
|
|
|
|
|
{"ip6_flow_find", get_ip6_flow_find},
|
|
|
|
|
{"ip6_flow_add", get_ip6_flow_add},
|
|
|
|
|
{"ip6_flow_del", get_ip6_flow_del},
|
|
|
|
|
{"ip6_flow_timeout", get_ip6_flow_timeout},
|
|
|
|
|
{"ip6_flow_fail_no_space", get_ip6_flow_fail_no_space},
|
|
|
|
|
{"ip6_flow_fail_overlap", get_ip6_flow_fail_overlap},
|
|
|
|
|
{"ip6_flow_fail_many_frag", get_ip6_flow_fail_many_frag},
|
|
|
|
|
{"ip6_flow_fail_invalid_length", get_ip6_flow_fail_invalid_length},
|
|
|
|
|
{"ip6_flow_bypass_dup_fist_frag", get_ip6_flow_bypass_dup_fist_frag},
|
|
|
|
|
{"ip6_flow_bypass_dup_last_frag", get_ip6_flow_bypass_dup_last_frag},
|
|
|
|
|
// TCP session
|
2024-08-14 11:25:04 +08:00
|
|
|
{"total_tcp_sess_used", get_total_tcp_sess_used},
|
|
|
|
|
{"curr_tcp_sess_used", get_curr_tcp_sess_used},
|
|
|
|
|
{"curr_tcp_sess_opening", get_curr_tcp_sess_opening},
|
|
|
|
|
{"curr_tcp_sess_active", get_curr_tcp_sess_active},
|
|
|
|
|
{"curr_tcp_sess_closing", get_curr_tcp_sess_closing},
|
|
|
|
|
{"curr_tcp_sess_discard", get_curr_tcp_sess_discard},
|
|
|
|
|
{"curr_tcp_sess_closed", get_curr_tcp_sess_closed},
|
2024-06-25 14:08:33 +08:00
|
|
|
// UDP session
|
2024-08-14 11:25:04 +08:00
|
|
|
{"total_udp_sess_used", get_total_udp_sess_used},
|
|
|
|
|
{"curr_udp_sess_used", get_curr_udp_sess_used},
|
|
|
|
|
{"curr_udp_sess_opening", get_curr_udp_sess_opening},
|
|
|
|
|
{"curr_udp_sess_active", get_curr_udp_sess_active},
|
|
|
|
|
{"curr_udp_sess_closing", get_curr_udp_sess_closing},
|
|
|
|
|
{"curr_udp_sess_discard", get_curr_udp_sess_discard},
|
|
|
|
|
{"curr_udp_sess_closed", get_curr_udp_sess_closed},
|
2024-06-25 14:08:33 +08:00
|
|
|
// Evicted session
|
2024-08-14 11:25:04 +08:00
|
|
|
{"tcp_sess_evicted", get_tcp_sess_evicted},
|
|
|
|
|
{"udp_sess_evicted", get_udp_sess_evicted},
|
2024-06-25 14:08:33 +08:00
|
|
|
// Packet
|
2024-08-16 18:32:35 +08:00
|
|
|
{"udp_pkts_bypass_table_full", get_udp_pkts_bypass_table_full},
|
|
|
|
|
{"tcp_pkts_bypass_table_full", get_tcp_pkts_bypass_table_full},
|
|
|
|
|
{"tcp_pkts_bypass_session_not_found", get_tcp_pkts_bypass_session_not_found},
|
|
|
|
|
{"tcp_pkts_bypass_duplicated", get_tcp_pkts_bypass_duplicated},
|
|
|
|
|
{"udp_pkts_bypass_duplicated", get_udp_pkts_bypass_duplicated},
|
|
|
|
|
{"udp_pkts_bypass_session_evicted", get_udp_pkts_bypass_session_evicted},
|
2024-06-25 14:08:33 +08:00
|
|
|
// TCP segments
|
2024-08-16 18:24:54 +08:00
|
|
|
{"tcp_segs_input", get_tcp_segs_input},
|
|
|
|
|
{"tcp_segs_timeout", get_tcp_segs_timeout},
|
|
|
|
|
{"tcp_segs_retransmited", get_tcp_segs_retransmited},
|
|
|
|
|
{"tcp_segs_overlapped", get_tcp_segs_overlapped},
|
|
|
|
|
{"tcp_segs_omitted_too_many", get_tcp_segs_omitted_too_many},
|
|
|
|
|
{"tcp_segs_inorder", get_tcp_segs_inorder},
|
|
|
|
|
{"tcp_segs_reordered", get_tcp_segs_reordered},
|
|
|
|
|
{"tcp_segs_buffered", get_tcp_segs_buffered},
|
|
|
|
|
{"tcp_segs_freed", get_tcp_segs_freed},
|
2024-06-25 14:08:33 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct stellar_stat
|
|
|
|
|
{
|
|
|
|
|
uint16_t nr_thread;
|
|
|
|
|
char output_file[2048];
|
|
|
|
|
struct fieldstat_easy *fs;
|
|
|
|
|
|
|
|
|
|
int flag[MAX_THREAD_NUM]; // IS_FREE or IS_BUSY
|
|
|
|
|
struct thread_stat thr_stat[MAX_THREAD_NUM];
|
|
|
|
|
|
|
|
|
|
struct metric_map
|
|
|
|
|
{
|
|
|
|
|
uint64_t key;
|
|
|
|
|
uint64_t val;
|
|
|
|
|
} map[sizeof(schemas) / sizeof(struct metric_schema)];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// python3 -m pip install prettytable
|
|
|
|
|
// python3 -m pip install jinja2
|
|
|
|
|
// /opt/MESA/bin/fieldstat_exporter.py local -j log/stellar_fs4.json -e -l --clear-screen
|
|
|
|
|
struct stellar_stat *stellar_stat_new(uint16_t nr_thread)
|
|
|
|
|
{
|
|
|
|
|
char cwd[1024] = {0};
|
|
|
|
|
struct stellar_stat *stat = (struct stellar_stat *)calloc(1, sizeof(struct stellar_stat));
|
|
|
|
|
if (stat == NULL)
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (getcwd(cwd, sizeof(cwd)) == NULL)
|
|
|
|
|
{
|
|
|
|
|
STAT_LOG_ERROR("failed to get current working directory: %s", strerror(errno));
|
|
|
|
|
goto error_out;
|
|
|
|
|
}
|
|
|
|
|
snprintf(stat->output_file, sizeof(stat->output_file), "%s/log/stellar_fs4.json", cwd);
|
|
|
|
|
|
|
|
|
|
stat->fs = fieldstat_easy_new(1, "stellar", NULL, 0);
|
|
|
|
|
if (stat->fs == NULL)
|
|
|
|
|
{
|
|
|
|
|
STAT_LOG_ERROR("failed to create fieldstat_easy");
|
|
|
|
|
goto error_out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stat->nr_thread = nr_thread;
|
|
|
|
|
for (int i = 0; i < MAX_THREAD_NUM; i++)
|
|
|
|
|
{
|
|
|
|
|
stat->flag[i] = IS_FREE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < sizeof(schemas) / sizeof(struct metric_schema); i++)
|
|
|
|
|
{
|
|
|
|
|
stat->map[i].key = fieldstat_easy_register_counter(stat->fs, schemas[i].name);
|
|
|
|
|
stat->map[i].val = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return stat;
|
|
|
|
|
|
|
|
|
|
error_out:
|
|
|
|
|
stellar_stat_free(stat);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void stellar_stat_free(struct stellar_stat *stat)
|
|
|
|
|
{
|
|
|
|
|
if (stat)
|
|
|
|
|
{
|
|
|
|
|
if (stat->fs)
|
|
|
|
|
{
|
|
|
|
|
fieldstat_easy_free(stat->fs);
|
|
|
|
|
stat->fs = NULL;
|
|
|
|
|
}
|
|
|
|
|
free(stat);
|
|
|
|
|
stat = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void stellar_stat_output(struct stellar_stat *stat)
|
|
|
|
|
{
|
|
|
|
|
for (uint16_t i = 0; i < stat->nr_thread; i++)
|
|
|
|
|
{
|
|
|
|
|
if (ATOMIC_READ(&(stat->flag[i])) == IS_BUSY)
|
|
|
|
|
{
|
|
|
|
|
struct thread_stat *thr_stat = &stat->thr_stat[i];
|
|
|
|
|
for (size_t j = 0; j < sizeof(schemas) / sizeof(struct metric_schema); j++)
|
|
|
|
|
{
|
|
|
|
|
stat->map[j].val += schemas[j].get_val(thr_stat);
|
|
|
|
|
}
|
|
|
|
|
memset(thr_stat, 0, sizeof(struct thread_stat));
|
|
|
|
|
ATOMIC_SET(&(stat->flag[i]), IS_FREE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (size_t j = 0; j < sizeof(schemas) / sizeof(struct metric_schema); j++)
|
|
|
|
|
{
|
|
|
|
|
fieldstat_easy_counter_set(stat->fs, 0, stat->map[j].key, NULL, 0, stat->map[j].val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *buff;
|
|
|
|
|
size_t len;
|
|
|
|
|
fieldstat_easy_output(stat->fs, &buff, &len);
|
|
|
|
|
if (buff)
|
|
|
|
|
{
|
|
|
|
|
FILE *fp = fopen(stat->output_file, "w+");
|
|
|
|
|
if (fp == NULL)
|
|
|
|
|
{
|
|
|
|
|
STAT_LOG_ERROR("failed to open file: %s, %s", stat->output_file, strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
fwrite(buff, len, 1, fp);
|
|
|
|
|
fflush(fp);
|
|
|
|
|
fclose(fp);
|
|
|
|
|
}
|
|
|
|
|
free(buff);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (size_t j = 0; j < sizeof(schemas) / sizeof(struct metric_schema); j++)
|
|
|
|
|
{
|
|
|
|
|
stat->map[j].val = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void stellar_stat_merge(struct stellar_stat *stat, const struct thread_stat *thr_stat, uint16_t thr_idx)
|
|
|
|
|
{
|
|
|
|
|
if (ATOMIC_READ(&(stat->flag[thr_idx])) == IS_FREE)
|
|
|
|
|
{
|
|
|
|
|
memcpy(&stat->thr_stat[thr_idx], thr_stat, sizeof(struct thread_stat));
|
|
|
|
|
ATOMIC_SET(&(stat->flag[thr_idx]), IS_BUSY);
|
|
|
|
|
}
|
|
|
|
|
}
|