2024-08-20 19:01:06 +08:00
|
|
|
#include <assert.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <pthread.h>
|
|
|
|
|
#include <unistd.h>
|
2024-08-16 14:58:19 +08:00
|
|
|
#include "http_decoder_private.h"
|
2024-08-20 19:01:06 +08:00
|
|
|
|
2024-08-16 14:58:19 +08:00
|
|
|
static const struct hd_stat_config_tuple g_httpd_stat_tuple[HTTP_STAT_MAX] =
|
|
|
|
|
{
|
|
|
|
|
{HTTP_C2S_BYTES, "http_c2s_bytes"},
|
|
|
|
|
{HTTP_S2C_BYTES, "http_s2c_bytes"},
|
|
|
|
|
{HTTP_C2S_TCP_SEG, "http_c2s_tcp_seg"},
|
|
|
|
|
{HTTP_S2C_TCP_SEG, "http_s2c_tcp_seg"},
|
|
|
|
|
{HTTP_C2S_HEADERS, "http_c2s_headers"},
|
|
|
|
|
{HTTP_S2C_HEADERS, "http_s2c_headers"},
|
|
|
|
|
{HTTP_C2S_ZIP_BYTES, "http_c2s_zip_bytes"},
|
|
|
|
|
{HTTP_S2C_ZIP_BYTES, "http_s2c_zip_bytes"},
|
|
|
|
|
{HTTP_C2S_UNZIP_BYTES, "http_c2s_unzip_bytes"},
|
|
|
|
|
{HTTP_S2C_UNZIP_BYTES, "http_s2c_unzip_bytes"},
|
|
|
|
|
{HTTP_URL_BYTES, "http_url_bytes"},
|
|
|
|
|
{HTTP_SESSION_NEW, "http_session_new"},
|
|
|
|
|
{HTTP_SESSION_FREE, "http_session_free"},
|
|
|
|
|
{HTTP_TRANSACTION_NEW, "http_transaction_new"},
|
|
|
|
|
{HTTP_TRANSACTION_FREE, "http_transaction_free"},
|
|
|
|
|
{HTTP_C2S_ASYMMETRY_SESSION, "http_c2s_asymmetry_sess"},
|
|
|
|
|
{HTTP_S2C_ASYMMETRY_SESSION, "http_s2c_asymmetry_sess"},
|
|
|
|
|
{HTTP_C2S_ASYMMETRY_TRANSACTION, "http_c2s_asymmetry_trans"},
|
|
|
|
|
{HTTP_S2C_ASYMMETRY_TRANSACTION, "http_s2c_asymmetry_trans"},
|
|
|
|
|
{HTTP_STAT_PARSE_ERR, "http_parse_error"},
|
|
|
|
|
};
|
2024-08-20 19:01:06 +08:00
|
|
|
|
|
|
|
|
void http_decoder_stat_free(struct http_decoder_stat *hd_stat)
|
|
|
|
|
{
|
2024-08-16 14:58:19 +08:00
|
|
|
if (hd_stat->timer_pid != 0)
|
|
|
|
|
{
|
2024-08-20 19:01:06 +08:00
|
|
|
pthread_cancel(hd_stat->timer_pid);
|
|
|
|
|
}
|
2024-08-16 14:58:19 +08:00
|
|
|
if (hd_stat->stats != NULL)
|
|
|
|
|
{
|
2024-08-20 19:01:06 +08:00
|
|
|
free(hd_stat->stats);
|
|
|
|
|
}
|
2024-08-16 14:58:19 +08:00
|
|
|
if (hd_stat->fse != NULL)
|
|
|
|
|
{
|
2024-08-20 19:01:06 +08:00
|
|
|
fieldstat_easy_free(hd_stat->fse);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void *httpd_stat_timer_thread(void *arg)
|
|
|
|
|
{
|
|
|
|
|
pthread_setname_np(pthread_self(), "http_decoder_timer_thread");
|
|
|
|
|
struct http_decoder_stat *hd_stat = (struct http_decoder_stat *)arg;
|
|
|
|
|
struct timespec res;
|
2024-08-16 14:58:19 +08:00
|
|
|
while (1)
|
|
|
|
|
{
|
2024-08-20 19:01:06 +08:00
|
|
|
clock_gettime(CLOCK_MONOTONIC, &res);
|
|
|
|
|
hd_stat->current_time_ms = (res.tv_sec * 1000) + (res.tv_nsec / 1000000);
|
|
|
|
|
usleep(800);
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int http_decoder_stat_init(struct http_decoder_stat *hd_stat, int thread_max, int stat_interval_pkts, int stat_interval_time)
|
|
|
|
|
{
|
2024-08-16 14:58:19 +08:00
|
|
|
assert(sizeof(g_httpd_stat_tuple) / sizeof(struct hd_stat_config_tuple) == HTTP_STAT_MAX);
|
|
|
|
|
if (sizeof(g_httpd_stat_tuple) / sizeof(struct hd_stat_config_tuple) != HTTP_STAT_MAX)
|
|
|
|
|
{
|
2024-08-20 19:01:06 +08:00
|
|
|
fprintf(stderr, "enum http_decoder_stat_type number not match with g_httpd_stat_tuple!");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
hd_stat->fse = fieldstat_easy_new(thread_max, "http_decoder_statistics", NULL, 0);
|
|
|
|
|
if (NULL == hd_stat->fse)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "fieldstat_easy_new failed.");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-16 14:58:19 +08:00
|
|
|
for (int i = 0; i < HTTP_STAT_MAX; i++)
|
2024-08-20 19:01:06 +08:00
|
|
|
{
|
|
|
|
|
hd_stat->field_stat_id[i] = fieldstat_easy_register_counter(hd_stat->fse, g_httpd_stat_tuple[i].name);
|
|
|
|
|
if (hd_stat->field_stat_id[i] < 0)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "fieldstat_easy_register_counter %s failed.", g_httpd_stat_tuple[i].name);
|
|
|
|
|
fieldstat_easy_free(hd_stat->fse);
|
|
|
|
|
hd_stat->fse = NULL;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-08-16 14:58:19 +08:00
|
|
|
|
2024-08-20 19:01:06 +08:00
|
|
|
int ret = fieldstat_easy_enable_auto_output(hd_stat->fse, FILEDSTAT_OUTPUT_FILE, stat_interval_time);
|
|
|
|
|
if (ret < 0)
|
|
|
|
|
{
|
|
|
|
|
fprintf(stderr, "fieldstat_easy_enable_auto_output failed.");
|
|
|
|
|
fieldstat_easy_free(hd_stat->fse);
|
2024-08-16 14:58:19 +08:00
|
|
|
hd_stat->fse = NULL;
|
2024-08-20 19:01:06 +08:00
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
hd_stat->stats = (struct hd_statistics *)calloc(thread_max, sizeof(struct hd_statistics));
|
|
|
|
|
hd_stat->stat_interval_pkts = stat_interval_pkts;
|
|
|
|
|
hd_stat->stat_interval_time = stat_interval_time;
|
|
|
|
|
pthread_create(&hd_stat->timer_pid, NULL, httpd_stat_timer_thread, hd_stat);
|
|
|
|
|
pthread_detach(hd_stat->timer_pid);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void http_decoder_stat_update(struct http_decoder_stat *hd_stat, int thread_id, enum http_decoder_stat_type type, long long value)
|
|
|
|
|
{
|
|
|
|
|
assert(hd_stat);
|
|
|
|
|
assert(thread_id >= 0);
|
2024-08-16 14:58:19 +08:00
|
|
|
assert(type < HTTP_STAT_MAX);
|
2024-08-20 19:01:06 +08:00
|
|
|
|
2024-08-16 14:58:19 +08:00
|
|
|
if (unlikely(hd_stat->stats == NULL))
|
|
|
|
|
{
|
2024-08-20 19:01:06 +08:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct hd_statistics *cur_hds = &hd_stat->stats[thread_id];
|
|
|
|
|
|
|
|
|
|
cur_hds->counter[type] += value;
|
|
|
|
|
cur_hds->batch[type]++;
|
|
|
|
|
|
2024-08-16 14:58:19 +08:00
|
|
|
if (cur_hds->batch[type] >= hd_stat->stat_interval_pkts || cur_hds->time_ms[type] + 1000 < hd_stat->current_time_ms)
|
|
|
|
|
{
|
|
|
|
|
fieldstat_easy_counter_incrby(hd_stat->fse, thread_id, hd_stat->field_stat_id[type], NULL, 0, cur_hds->counter[type]);
|
|
|
|
|
cur_hds->counter[type] = 0;
|
|
|
|
|
cur_hds->batch[type] = 0;
|
|
|
|
|
cur_hds->time_ms[type] = hd_stat->current_time_ms;
|
2024-08-20 19:01:06 +08:00
|
|
|
}
|
|
|
|
|
}
|