obconnector-c/include/ob_full_link_trace.h
2024-06-03 16:47:46 +08:00

461 lines
17 KiB
C

/*
Copyright (c) 2000, 2018, Oracle and/or its affiliates.
Copyright (c) 2009, 2019, MariaDB Corporation.
Copyright (c) 2021 OceanBase.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
#ifndef _ob_full_link_trace_h
#define _ob_full_link_trace_h
#include <stdint.h>
#include "mysql.h"
#include "ma_list.h"
#include "ob_thread_key.h"
// #define DEBUG_OB20
#define UUID4_LEN 37
#define UUID4_SERIALIZE_LEN 16
#define FLT_DECLARE \
Ob20Protocol *ob20protocol = mysql->net.ob20protocol; \
FLTInfo *flt = NULL; \
ObSpanCtx *span; \
ObTrace *trace; \
char ip_buffer[50] = {0}; \
char host_buffer[50] = {0}; \
int port = 0
#define FLT_BEFORE_COMMAND(span_level, tag_level, tag_str) \
do \
{ \
if (get_use_full_link_trace(mysql) && OB_NOT_NULL(ob20protocol)) { \
flt = ob20protocol->flt; \
if (OB_NOT_NULL(flt)) { \
if ((TRUE == flt->control_info_.flt_show_trace_enable_) \
|| !(mysql->server_status & SERVER_STATUS_IN_TRANS)) { \
BEGIN_TRACE(flt); \
} else { \
/* A reset is required before each begin in the current transaction to prevent insufficient span*/ \
reset_span(flt->trace_); \
} \
span = BEGIN_SPAN(flt, span_level); \
SET_TAG(flt, tag_level, tag_str); \
if (NULL != mysql && get_local_ip_port(mysql->net.fd, ip_buffer, 50, &port)) { \
snprintf(host_buffer, 50, "\"%s:%d\"", ip_buffer, port); \
SET_TAG(flt, FLT_TAG_CLIENT_HOST, host_buffer); \
} \
if (flt_build_request(mysql, flt)) { \
/* error , but do nothing */ \
} \
} \
} \
} while (0)
#define FLT_AFTER_COMMAND \
do \
{ \
ob20protocol = mysql->net.ob20protocol; \
if (get_use_full_link_trace(mysql) && OB_NOT_NULL(ob20protocol)) { \
flt = ob20protocol->flt; \
trace = OBTRACE(flt); \
if (NULL != trace) { \
END_SPAN(flt, span); \
if (TRUE == trace->force_print_) { \
FLUSH_TRACE(flt); \
} else if (TRUE == trace->slow_query_print_) { \
trace->slow_query_print_ = FALSE; /* Slow query is set to FALSE for each request */ \
flush_first_span(trace); \
} \
if ((TRUE == flt->control_info_.flt_show_trace_enable_) \
|| !(mysql->server_status & SERVER_STATUS_IN_TRANS)) { \
END_TRACE(flt); \
} \
} \
} \
} while (0)
#define DEFINE_FLT_SERIALIZE_FUNC(type) \
int flt_serialize_##type(char *buf, const int64_t len, int64_t *pos, void *flt_info); \
int flt_get_serialize_size_##type(int32_t *size, void *flt_info); \
int flt_deserialize_field_##type(FullLinkTraceExtraInfoId extra_id, const int64_t v_len, \
const char *buf, const int64_t len, int64_t *pos, void *flt_info)
#define FLT_SERIALIZE_FUNC(type) \
{ \
flt_deserialize_field_##type, \
flt_serialize_##type, \
flt_get_serialize_size_##type \
}
#define DEFINE_TO_STRING_FUNC_FOR(type) \
int tostring_##type(char *buf, const int64_t buf_len, int64_t *pos, type *src)
// Currently maintains a size of 5k for each trace, which is the size of all space allocated during the entire trace
#define OBTRACE_DEFAULT_BUFFER_SIZE (5 * (1L << 10))
// The current driver free span is 4
#define SPAN_CACHE_COUNT (1L << 2)
// The current driver free span is 4
#define TAG_CACHE_COUNT (1L << 4)
// Since there is currently at most one SPAN, the largest LOG buffer is 1k
#define MAX_TRACE_LOG_SIZE (1L << 10)
// The current maximum size of the full link after serialization is 2k
#define MAX_FLT_SERIALIZE_SIZE (1L << 11)
// span cache begin buffer
#define TAG_BUFFER_BEGIN ((2 * MAX_TRACE_LOG_SIZE) + MAX_FLT_SERIALIZE_SIZE)
#define SPAN_BUFFER_BEGIN ((2 * MAX_TRACE_LOG_SIZE) + MAX_FLT_SERIALIZE_SIZE + TAG_CACHE_COUNT * (sizeof(ObTagCtx)))
#define INIT_OFFSET (SPAN_BUFFER_BEGIN + SPAN_CACHE_COUNT * (sizeof(LIST) + sizeof(ObSpanCtx)))
#define OBTRACE(flt) get_trace_instance(flt)
#define BEGIN_TRACE(flt) (begin_trace(OBTRACE(flt)))
#define END_TRACE(flt) \
do \
{ \
end_trace(OBTRACE(flt)); \
} while (0)
#define BEGIN_SPAN(flt, span_type) BEGIN_CHILD_SPAN(flt, span_type)
#define BEGIN_CHILD_SPAN(flt, span_type) (begin_span(OBTRACE(flt), span_type, 1, FALSE))
#define BEGIN_FOLLOW_SPAN(flt, span_type) (begin_span(OBTRACE(flt), span_type, 1, TRUE))
#define END_SPAN(flt, span_id) \
do \
{ \
ObTrace *trace = OBTRACE(flt); \
(end_span(trace, span_id)); \
} while (0)
#define SET_TAG(flt, tag_type, value) \
do \
{ \
ObSpanCtx *span = OBTRACE(flt)->last_active_span_; \
if (OB_NOT_NULL(span)) { \
append_tag(OBTRACE(flt), span, tag_type, value); \
} \
} while (0)
#define SET_TRACE_LEVEL(trace, level) (trace->level_ = level)
#define SET_AUTO_FLUSH(trace, value) (trace->auto_flush_ = value)
#define FLUSH_TRACE(flt) \
do \
{ \
flush_trace(OBTRACE(flt)); \
} while (0)
typedef struct st_obtrace ObTrace;
/*
0 ~ 999 for obclient
1000~1999 for obproxy
2000~65535 for all
*/
typedef enum enum_fulllinktraceextrainfoid
{
FLT_DRIVER_SPAN = 1,
FLT_DRIVER_END = 1000,
// APP_INFO
FLT_CLIENT_IDENTIFIER = 2001,
FLT_MODULE,
FLT_ACTION,
FLT_CLIENT_INFO,
FLT_APPINFO_TYPE,
// QUERY_INFO
FLT_QUERY_START_TIMESTAMP = 2010,
FLT_QUERY_END_TIMESTAMP,
// CONTROL_INFO
FLT_LEVEL = 2020,
FLT_SAMPLE_PERCENTAGE,
FLT_RECORD_POLICY,
FLT_PRINT_SAMPLE_PCT,
FLT_SLOW_QUERY_THRES,
FLT_SHOW_TRACE_ENABLE,
// SPAN_INFO
FLT_TRACE_ENABLE = 2030,
FLT_FORCE_PRINT,
FLT_TRACE_ID,
FLT_REF_TYPE,
FLT_SPAN_ID,
// FLT_SHOW_TRACE
FLT_DRV_SHOW_TRACE_SPAN = 2050,
FLT_PROXY_SHOW_TRACE_SPAN,
FLT_EXTRA_INFO_ID_END
} FullLinkTraceExtraInfoId;
/*
0 ~ 999 for obclient
1000~1999 for obproxy
2000~65535 for all
*/
typedef enum enum_fulllinktraceextrainfotype
{
FLT_DRIVER_SPAN_INFO = 1,
FLT_EXTRA_INFO_DRIVE_END = 1000,
FLT_APP_INFO = 2001,
FLT_QUERY_INFO,
FLT_CONTROL_INFO,
FLT_SPAN_INFO,
FLT_TYPE_SHOW_TRACE_SPAN,
FLT_EXTRA_INFO_TYPE_END
} FullLinkTraceExtraInfoType;
typedef enum enum_recordpolicy {
RP_ALL = 1,
RP_ONLY_SLOW_QUERY,
RP_SAMPLE_AND_SLOW_QUERY,
MAX_RECORD_POLICY
} RecordPolicy;
typedef struct st_fltinfobase
{
FullLinkTraceExtraInfoType type_;
} FLTInfoBase;
typedef struct st_fltcontrolinfo
{
FullLinkTraceExtraInfoType type_;
int8_t level_;
double sample_pct_;
RecordPolicy rp_;
double print_sample_pct_;
int64_t slow_query_threshold_;
int8_t flt_show_trace_enable_; // enable show trace or not
} FLTControlInfo;
typedef struct st_fltappinfo
{
FullLinkTraceExtraInfoType type_;
const char *identifier_;
const char *module_;
const char *action_;
const char *client_info_;
} FLTAppInfo;
typedef struct st_fltqueryinfo
{
FullLinkTraceExtraInfoType type_;
int64_t query_start_timestamp_;
int64_t query_end_timestamp_;
} FLTQueryInfo;
typedef struct st_fltspaninfo
{
FullLinkTraceExtraInfoType type_;
int8_t trace_enable_;
int8_t force_print_;
const char *trace_id_;
int8_t ref_type_;
const char *span_id_;
} FLTSpanInfo;
typedef struct st_fltdriverspaninfo
{
FullLinkTraceExtraInfoType type_;
const char *client_span_;
} FLTDriverSpanInfo;
typedef struct st_showtracespan
{
FullLinkTraceExtraInfoType type_;
const char *client_span_json_;
} FLTShowTraceSpan;
typedef struct st_fltvaluedata
{
void *value_data_;
size_t length;
} FLTValueData;
typedef struct st_fltinfo
{
FLTShowTraceSpan show_trace_span_;
FLTDriverSpanInfo client_span_;
FLTControlInfo control_info_;
FLTAppInfo app_info_;
FLTQueryInfo query_info_;
FLTSpanInfo span_info_;
FLTValueData flt_value_data_; // for set extra info
my_bool in_trans_;
char trace_id_[UUID4_SERIALIZE_LEN];
char span_id_[UUID4_SERIALIZE_LEN];
ObTrace *trace_;
} FLTInfo;
typedef int (*flt_deserialize_field_func)(FullLinkTraceExtraInfoId extra_id, const int64_t v_len,
const char *buf, const int64_t len, int64_t *pos, void *flt_info);
typedef int (*flt_serialize_func)(char *buf, const int64_t len, int64_t *pos, void *flt_info);
typedef int (*flt_get_serialize_size_func)(int32_t *size, void *flt_info);
typedef struct st_fltfunc
{
flt_deserialize_field_func deserialize_field_func;
flt_serialize_func serialize_func;
flt_get_serialize_size_func get_serialize_size_func;
} FLTFunc;
typedef struct st_obclient_uuid
{
union {
struct {
uint64_t low_;
uint64_t high_;
};
struct {
uint32_t time_low;
uint16_t time_mid;
uint16_t time_hi_and_version;
uint8_t clock_seq_hi_and_reserved;
uint8_t clock_seq_low;
uint8_t node[6];
};
};
} OBCLIENT_UUID;
DEFINE_TO_STRING_FUNC_FOR(OBCLIENT_UUID);
enum enum_flt_tagtype{
FLT_TAG_COMMAND_NAME = 0,
FLT_TAG_CLIENT_HOST = 1,
FLT_TAG_MAX_TYPE
};
typedef struct st_obtagctx ObTagCtx;
struct st_obtagctx
{
ObTagCtx *next_;
uint16_t tag_type_;
const char *data_;
};
DEFINE_TO_STRING_FUNC_FOR(ObTagCtx);
typedef struct st_obspanctx
{
uint16_t span_type_;
OBCLIENT_UUID span_id_;
struct st_obspanctx *source_span_;
my_bool is_follow_;
int64_t start_ts_;
int64_t end_ts_;
ObTagCtx *tags_;
} ObSpanCtx;
DEFINE_TO_STRING_FUNC_FOR(ObSpanCtx);
struct st_obtrace
{
uint64_t buffer_size_;
uint64_t offset_;
uint64_t seq_;
my_bool in_trans_;
my_bool trace_enable_;
my_bool show_trace_enable_;
my_bool force_print_;
my_bool slow_query_print_;
FLTInfo *flt; // point to flt struct
uint64_t uuid_random_seed[2];
OBCLIENT_UUID trace_id_;
OBCLIENT_UUID root_span_id_;
LIST *current_span_list_;
LIST *free_span_list_;
ObSpanCtx *last_active_span_;
ObTagCtx free_tag_list_;
union {
uint8_t policy_;
struct {
uint8_t level_ : 7;
uint8_t auto_flush_ : 1;
};
};
uint64_t log_buf_offset_;
char *log_buf_; // size is MAX_TRACE_LOG_SIZE
uint64_t show_trace_buf_offset_;
char *show_trace_buf_; // size is MAX_TRACE_LOG_SIZE
char *flt_serialize_buf_; // size is MAX_FLT_SERIALIZE_SIZE
char data_[0]; // Multi-allocated space to store free span and facilitate subsequent tagging
};
int trace_init();
void trace_end();
void begin_trace(ObTrace *trace);
void end_trace(ObTrace *trace);
ObSpanCtx* begin_span(ObTrace *trace, uint32_t span_type, uint8_t level, my_bool is_follow);
void end_span(ObTrace *trace, ObSpanCtx *span);
void reset_span(ObTrace *trace);
void append_tag(ObTrace *trace, ObSpanCtx *span, uint16_t tag_type, const char *str);
void reset_tag(ObTrace *trace, ObSpanCtx *span, ObTagCtx *tag);
ObTrace *get_trace_instance(FLTInfo *flt);
void flush_first_span(ObTrace *trace);
void flush_trace(ObTrace *trace);
DEFINE_FLT_SERIALIZE_FUNC(appinfo); // FLT_APP_INFO
DEFINE_FLT_SERIALIZE_FUNC(queryinfo); // FLT_QUERY_INFO
DEFINE_FLT_SERIALIZE_FUNC(controlinfo); // FLT_CONTROL_INFO
DEFINE_FLT_SERIALIZE_FUNC(spaninfo); // FLT_SPAN_INFO
DEFINE_FLT_SERIALIZE_FUNC(driverspaninfo); // FLT_DRIVER_SPAN_INFO
DEFINE_FLT_SERIALIZE_FUNC(showtracespan); // FLT_TYPE_SHOW_TRACE_SPAN
DEFINE_FLT_SERIALIZE_FUNC(nosupport); // FLT_EXTRA_INFO_TYPE_END
my_bool flt_is_vaild(FLTInfo *flt);
int serialize_UUID(char *buf, const int64_t buf_len, int64_t* pos, OBCLIENT_UUID *uuid);
int deserialize_UUID(const char *buf, const int64_t buf_len, int64_t *pos, OBCLIENT_UUID *uuid);
int uuid4_init(uint64_t *seed, size_t seed_size);
OBCLIENT_UUID uuid4_generate(uint64_t *seed);
int flt_init(FLTInfo *flt);
void flt_end(FLTInfo *flt);
int flt_build_request(MYSQL *mysql, FLTInfo *flt);
void flt_set_send_trans_flag(FLTInfo *flt, my_bool send_flag);
int flt_deserialize_extra_info(const char *buf, const int64_t len, int64_t *pos, FullLinkTraceExtraInfoType type, void *flt_info);
int flt_serialize_extra_info(char *buf, const int64_t len, int64_t *pos, void *flt_info);
int flt_get_serialize_size_extra_info(int32_t *size, void *flt_info);
// for encode
int flt_store_type_and_len(char *buf, int64_t len, int64_t *pos, int16_t type, int32_t v_len);
int flt_store_str(char *buf, int64_t len, int64_t *pos, const char *str, const uint64_t str_len, int16_t type);
//@{Serialize integer data, save the data in v to the position of buf+pos, and update pos
int flt_store_int1(char *buf, int64_t len, int64_t *pos, int8_t v, int16_t type);
int flt_store_int2(char *buf, int64_t len, int64_t *pos, int16_t v, int16_t type);
int flt_store_int3(char *buf, int64_t len, int64_t *pos, int32_t v, int16_t type);
int flt_store_int4(char *buf, int64_t len, int64_t *pos, int32_t v, int16_t type);
int flt_store_int5(char *buf, int64_t len, int64_t *pos, int64_t v, int16_t type);
int flt_store_int6(char *buf, int64_t len, int64_t *pos, int64_t v, int16_t type);
int flt_store_int8(char *buf, int64_t len, int64_t *pos, int64_t v, int16_t type);
int flt_store_double(char *buf, const int64_t len, int64_t *pos, double val, int16_t type);
int flt_store_float(char *buf, const int64_t len, int64_t *pos, float val, int16_t type);
int flt_get_store_str_size(const uint64_t str_len);
int flt_get_store_int1_size();
int flt_get_store_int2_size();
int flt_get_store_int3_size();
int flt_get_store_int4_size();
int flt_get_store_int5_size();
int flt_get_store_int6_size();
int flt_get_store_int8_size();
int flt_get_store_double_size();
int flt_get_store_float_size();
// for decode
int flt_resolve_type_and_len(const char *buf, int64_t len, int64_t *pos, int16_t *type, int32_t *v_len);
int flt_get_str(const char *buf, int64_t len, int64_t *pos, int64_t str_len, char **str);
//@{ Signed integer in reverse sequence, write the result to v, and update pos
int flt_get_int1(const char *buf, int64_t len, int64_t *pos, int64_t v_len, int8_t *val);
int flt_get_int2(const char *buf, int64_t len, int64_t *pos, int64_t v_len, int16_t *val);
int flt_get_int3(const char *buf, int64_t len, int64_t *pos, int64_t v_len, int32_t *val);
int flt_get_int4(const char *buf, int64_t len, int64_t *pos, int64_t v_len, int32_t *val);
int flt_get_int8(const char *buf, int64_t len, int64_t *pos, int64_t v_len, int64_t *val);
int flt_get_double(const char *buf, int64_t len, int64_t *pos, int64_t v_len, double *val);
int flt_get_float(const char *buf, int64_t len, int64_t *pos, int64_t v_len, float *val);
#endif