#include "ob_full_link_trace.h" #include #include #include #if defined(_WIN32) #include #include #else #include #endif #include "ob_rwlock.h" #include "ma_global.h" #include "mariadb_com.h" #include "ob_protocol20.h" #include "ob_serialize.h" #include "ob_utils.h" #define TYPE_LENGTH 2 #define LEN_LENGTH 4 #define FLT_SIZE sizeof(float) #define DBL_SIZE sizeof(double) #define UUID_PATTERN "%8.8lx-%4.4lx-%4.4lx-%4.4lx-%12.12lx" #define TRACE_PATTERN "{\"trace_id\":\""UUID_PATTERN"\",\"name\":\"%s\",\"id\":\""UUID_PATTERN"\",\"start_ts\":%ld,\"end_ts\":%ld,\"parent_id\":\""UUID_PATTERN"\",\"is_follow\":%s" #define UUID_TOSTRING(uuid) \ ((uuid).high_ >> 32), ((uuid).high_ >> 16 & 0xffff), ((uuid).high_ & 0xffff), \ ((uuid).low_ >> 48), ((uuid).low_ & 0xffffffffffff) #define INIT_SPAN(trace, span) \ if (OB_NOT_NULL(span) && 0 == span->span_id_.high_) { \ span->span_id_.low_ = xorshift128plus(trace->uuid_random_seed); \ span->span_id_.high_ = span->start_ts_; \ } #define sint1korr(A) (*((int8_t*)(A))) #define FLT_EXTRA_INFO_DEF(id, type) (id2type[id] = type) #define FLT_EXTRA_INFO_INIT() \ do \ { \ /* FLT_DRIVER_SPAN_INFO */ \ FLT_EXTRA_INFO_DEF(FLT_DRIVER_SPAN , MYSQL_TYPE_VAR_STRING); \ /* APP_INFO */ \ FLT_EXTRA_INFO_DEF(FLT_CLIENT_IDENTIFIER, MYSQL_TYPE_VAR_STRING); \ FLT_EXTRA_INFO_DEF(FLT_MODULE, MYSQL_TYPE_VAR_STRING); \ FLT_EXTRA_INFO_DEF(FLT_ACTION, MYSQL_TYPE_VAR_STRING); \ FLT_EXTRA_INFO_DEF(FLT_CLIENT_INFO, MYSQL_TYPE_VAR_STRING); \ /* QUERY_INFO */ \ FLT_EXTRA_INFO_DEF(FLT_QUERY_START_TIMESTAMP, MYSQL_TYPE_LONGLONG); \ FLT_EXTRA_INFO_DEF(FLT_QUERY_END_TIMESTAMP, MYSQL_TYPE_LONGLONG); \ /* CONTROL_INFO */ \ FLT_EXTRA_INFO_DEF(FLT_LEVEL, MYSQL_TYPE_TINY); \ FLT_EXTRA_INFO_DEF(FLT_SAMPLE_PERCENTAGE, MYSQL_TYPE_DOUBLE); \ FLT_EXTRA_INFO_DEF(FLT_RECORD_POLICY, MYSQL_TYPE_TINY); \ FLT_EXTRA_INFO_DEF(FLT_PRINT_SAMPLE_PCT, MYSQL_TYPE_DOUBLE); \ FLT_EXTRA_INFO_DEF(FLT_SLOW_QUERY_THRES, MYSQL_TYPE_LONGLONG); \ /* SPAN_INFO */ \ FLT_EXTRA_INFO_DEF(FLT_TRACE_ENABLE, MYSQL_TYPE_TINY); \ FLT_EXTRA_INFO_DEF(FLT_FORCE_PRINT, MYSQL_TYPE_TINY); \ FLT_EXTRA_INFO_DEF(FLT_TRACE_ID, MYSQL_TYPE_VAR_STRING); \ FLT_EXTRA_INFO_DEF(FLT_REF_TYPE, MYSQL_TYPE_TINY); \ FLT_EXTRA_INFO_DEF(FLT_SPAN_ID, MYSQL_TYPE_VAR_STRING); \ /* SHOW_TRACE_SPAN */ \ FLT_EXTRA_INFO_DEF(FLT_DRV_SHOW_TRACE_SPAN, MYSQL_TYPE_VAR_STRING); \ FLT_EXTRA_INFO_DEF(FLT_PROXY_SHOW_TRACE_SPAN, MYSQL_TYPE_VAR_STRING); \ FLT_EXTRA_INFO_DEF(FLT_EXTRA_INFO_ID_END, MAX_NO_FIELD_TYPES); \ } while (0); #define FLT_SERIALIZE_FUNC_SET(id, funcname) (flt_funcs[id] = (FLTFunc)FLT_SERIALIZE_FUNC(funcname)) #define FLT_SERIALIZE_FUNC_INIT() \ do \ { \ /* FLT_DRIVER_SPAN_INFO */ \ FLT_SERIALIZE_FUNC_SET(FLT_DRIVER_SPAN_INFO, driverspaninfo); \ /* APP_INFO */ \ FLT_SERIALIZE_FUNC_SET(FLT_APP_INFO, appinfo); \ /* QUERY_INFO */ \ FLT_SERIALIZE_FUNC_SET(FLT_QUERY_INFO, queryinfo); \ /* CONTROL_INFO */ \ FLT_SERIALIZE_FUNC_SET(FLT_CONTROL_INFO, controlinfo); \ /* SPAN_INFO */ \ FLT_SERIALIZE_FUNC_SET(FLT_SPAN_INFO, spaninfo); \ /* SHOW_TRACE_SPAN */ \ FLT_SERIALIZE_FUNC_SET(FLT_TYPE_SHOW_TRACE_SPAN, showtracespan); \ } while (0); const char *tag_str[FLT_TAG_MAX_TYPE] = { "command_name", "client_host" }; static ob_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER; static int init_flag = 0; static enum_field_types id2type[FLT_EXTRA_INFO_ID_END + 1]; static FLTFunc flt_funcs[FLT_EXTRA_INFO_TYPE_END + 1]; static uint64_t xorshift128plus(uint64_t *s); inline void flt_set_send_trans_flag(FLTInfo *flt, my_bool flag) { if (OB_NOT_NULL(flt)) { flt->in_trans_ = flag; } } static inline double flt_get_pct(uint64_t *seed) { uint64_t rand64; /* Use the method of generating random numbers in uuid to get random numbers */ rand64 = xorshift128plus(seed); return (double)rand64 / UINT64_MAX; } int flt_init(FLTInfo *flt) { int ret = OB_SUCCESS; if (OB_NOT_NULL(flt)) { if (!init_flag) { ob_mutex_lock(&init_mutex); if (!init_flag) { FLT_EXTRA_INFO_INIT(); // init id2type FLT_SERIALIZE_FUNC_INIT(); // init flt_funcs init_flag = 1; } ob_mutex_unlock(&init_mutex); } memset(flt, 0, sizeof(*flt)); flt->show_trace_span_.type_ = FLT_TYPE_SHOW_TRACE_SPAN; flt->client_span_.type_ = FLT_DRIVER_SPAN_INFO; flt->app_info_.type_ = FLT_APP_INFO; flt->query_info_.type_ = FLT_QUERY_INFO; flt->span_info_.type_ = FLT_SPAN_INFO; flt->control_info_.type_ = FLT_CONTROL_INFO; flt->in_trans_ = FALSE; // init control info flt->control_info_.level_ = -1; flt->control_info_.sample_pct_ = -1; flt->control_info_.rp_ = MAX_RECORD_POLICY; flt->control_info_.print_sample_pct_ = -1; flt->control_info_.slow_query_threshold_ = -1; flt->control_info_.flt_show_trace_enable_ = 0; if (OB_FAIL(trace_init(flt))) { // trace init error; } } return ret; } void flt_end(FLTInfo *flt) { trace_end(flt); } my_bool flt_is_vaild(FLTInfo *flt) { my_bool ret = FALSE; if (OB_ISNULL(flt)) { // do nothing } else { FLTControlInfo *control = &flt->control_info_; if (control->level_ > 0 && (control->sample_pct_ >= 0 && control->sample_pct_ <= 1) && control->rp_ < MAX_RECORD_POLICY && (control->print_sample_pct_ >= 0 && control->print_sample_pct_ <= 1)) { ret = TRUE; } } return ret; } int flt_build_request(MYSQL *mysql, FLTInfo *flt) { int ret = OB_SUCCESS; ObTrace *trace = OBTRACE(flt); ObSpanCtx *span; if (OB_ISNULL(trace) || OB_ISNULL(flt)) { ret = OB_ERROR; } else { // build request int32_t serialize_size = 0; int32_t span_info_serialize_size = 0; int32_t client_log_serialize_size = 0; int32_t app_info_serialize_size = 0; int32_t show_trace_serialize_size = 0; int64_t tmp_trace_id_pos = 0; int64_t tmp_span_id_pos = 0; span = trace->last_active_span_; if (TRUE == trace->trace_enable_ && NULL != span) { INIT_SPAN(trace, span); // When trace enable is true, span info needs to be sent if (OB_FAIL(serialize_UUID(flt->trace_id_, UUID4_SERIALIZE_LEN, &tmp_trace_id_pos, &trace->trace_id_))) { // error } else if (OB_FAIL(serialize_UUID(flt->span_id_, UUID4_SERIALIZE_LEN, &tmp_span_id_pos, &span->span_id_))) { // error } else { flt->span_info_.trace_id_ = flt->trace_id_; flt->span_info_.span_id_ = flt->span_id_; flt->span_info_.type_ = FLT_SPAN_INFO; flt->span_info_.trace_enable_ = trace->trace_enable_; flt->span_info_.force_print_ = trace->force_print_; if (trace->force_print_) { FLUSH_TRACE(flt); } } } else { flt->span_info_.trace_enable_ = FALSE; } if (OB_SUCC(ret)) { if (0 != trace->log_buf_offset_) { flt->client_span_.client_span_ = trace->log_buf_; } else { flt->client_span_.client_span_ = NULL; } if (1 < trace->show_trace_buf_offset_ && trace->show_trace_enable_) { flt->show_trace_span_.client_span_json_ = trace->show_trace_buf_; // Change the final comma to a parenthesis trace->show_trace_buf_[trace->show_trace_buf_offset_ - 1] = ']'; } else { flt->show_trace_span_.client_span_json_ = NULL; } if (OB_FAIL(flt_get_serialize_size_extra_info(&app_info_serialize_size, &flt->app_info_))) { // error } else if (OB_FAIL(flt_get_serialize_size_extra_info(&client_log_serialize_size, &flt->client_span_))) { // error } else if (OB_FAIL(flt_get_serialize_size_extra_info(&span_info_serialize_size, &flt->span_info_))) { // error } else if (OB_FAIL(flt_get_serialize_size_extra_info(&show_trace_serialize_size, &flt->show_trace_span_))) { // error } else { serialize_size += app_info_serialize_size; serialize_size += client_log_serialize_size; serialize_size += span_info_serialize_size; serialize_size += show_trace_serialize_size; #ifdef DEBUG_OB20 printf("spaninfo ssize:%d, log ssize:%d, appinfo ssize:%d, show trace ssize:%d\n", span_info_serialize_size, client_log_serialize_size, app_info_serialize_size, show_trace_serialize_size); if (0 != client_log_serialize_size) { printf("log:%s\n", flt->client_span_.client_span_); } if (0 != show_trace_serialize_size) { printf("log:%s\n", flt->show_trace_span_.client_span_json_); } #endif } if (OB_SUCC(ret) && 0 != serialize_size) { if (MAX_FLT_SERIALIZE_SIZE < serialize_size) { ret = OB_ERROR; } else { int64_t pos = 0; flt->flt_value_data_.length = serialize_size; flt->flt_value_data_.value_data_ = trace->flt_serialize_buf_; if (OB_FAIL(flt_serialize_extra_info(flt->flt_value_data_.value_data_, serialize_size, &pos, &flt->span_info_))) { // error } else if (pos != span_info_serialize_size) { ret = OB_ERROR; } else if (0 != client_log_serialize_size && OB_FAIL(flt_serialize_extra_info(flt->flt_value_data_.value_data_, serialize_size, &pos, &flt->client_span_))) { // error } else if (pos != span_info_serialize_size + client_log_serialize_size) { ret = OB_ERROR; } else if (0 != show_trace_serialize_size && OB_FAIL(flt_serialize_extra_info(flt->flt_value_data_.value_data_, serialize_size, &pos, &flt->show_trace_span_))) { // error } else if (pos != span_info_serialize_size + client_log_serialize_size + show_trace_serialize_size) { ret = OB_ERROR; } else if (0 != app_info_serialize_size && OB_FAIL(flt_serialize_extra_info(flt->flt_value_data_.value_data_, serialize_size, &pos, &flt->app_info_))) { // error } else if (pos != serialize_size) { ret = OB_ERROR; } else { if (0 != app_info_serialize_size) { // clear app info memset(&flt->app_info_, 0, sizeof(flt->app_info_)); flt->app_info_.type_ = FLT_APP_INFO; } // reset the log buf offset trace->log_buf_offset_ = 0; flt->client_span_.client_span_ = NULL; // reset show trace log buffer trace->show_trace_buf_[0] = '['; trace->show_trace_buf_offset_ = 1; flt->show_trace_span_.client_span_json_ = NULL; } if (OB_SUCC(ret)) { if (OB_FAIL(ob20_set_extra_info(mysql, FULL_TRC, &flt->flt_value_data_))) { // error } } } } } } return ret; } int flt_deserialize_extra_info(const char *buf, const int64_t len, int64_t *pos, FullLinkTraceExtraInfoType type, void *flt_info) { int ret = OB_SUCCESS; while (OB_SUCC(ret) && *pos < len) { int32_t val_len = 0; int16_t extra_id; if (OB_FAIL(flt_resolve_type_and_len(buf, len, pos, &extra_id, &val_len))) { ret = OB_ERROR; } else if (OB_FAIL(flt_funcs[type].deserialize_field_func((FullLinkTraceExtraInfoId)(extra_id), val_len, buf, len, pos, flt_info))) { ret = OB_ERROR; } else { // do nothing } } return ret; } int flt_serialize_extra_info(char *buf, const int64_t len, int64_t *pos, void *flt_info) { int ret = OB_SUCCESS; FullLinkTraceExtraInfoType type = ((FLTInfoBase *)flt_info)->type_; ret = flt_funcs[type].serialize_func(buf, len, pos, flt_info); return ret; } int flt_get_serialize_size_extra_info(int32_t *size, void *flt_info) { int ret = OB_SUCCESS; FullLinkTraceExtraInfoType type = ((FLTInfoBase *)flt_info)->type_; ret = flt_funcs[type].get_serialize_size_func(size, flt_info); return ret; } // for control info int flt_get_serialize_size_controlinfo(int32_t *size, void *flt_info) { int ret = OB_SUCCESS; int32_t local_size = 0; UNUSED(flt_info); local_size += TYPE_LENGTH + LEN_LENGTH; local_size += flt_get_store_int1_size(); // type_ local_size += flt_get_store_double_size(); // sample_pct_ local_size += flt_get_store_int1_size(); // rp_ local_size += flt_get_store_double_size(); // print_sample_pct_ local_size += flt_get_store_int8_size(); // slow_query_threshold_ local_size += flt_get_store_int8_size(); // flt_show_trace_enable_ *size = local_size; return ret; } int flt_serialize_controlinfo(char *buf, const int64_t len, int64_t *pos, void *flt_info) { int ret = OB_SUCCESS; int64_t org_pos = *pos; FLTControlInfo *control_info = (FLTControlInfo *)flt_info; // resrver for type and len if (*pos + 6 > len) { ret = OB_SIZE_OVERFLOW; } else { *pos += 6; } if (OB_FAIL(ret)) { // do nothing } else if (OB_FAIL(flt_store_int1(buf, len, pos, control_info->level_, FLT_LEVEL))) { ret = OB_ERROR; } else if (OB_FAIL(flt_store_double(buf, len, pos, control_info->sample_pct_, FLT_SAMPLE_PERCENTAGE))) { ret = OB_ERROR; } else if (OB_FAIL(flt_store_int1(buf, len, pos, control_info->rp_, FLT_RECORD_POLICY))) { ret = OB_ERROR; } else if (OB_FAIL(flt_store_double(buf, len, pos, control_info->print_sample_pct_, FLT_PRINT_SAMPLE_PCT))) { ret = OB_ERROR; } else if (OB_FAIL(flt_store_int8(buf, len, pos, control_info->slow_query_threshold_, FLT_SLOW_QUERY_THRES))) { ret = OB_ERROR; } else if (OB_FAIL(flt_store_int8(buf, len, pos, control_info->flt_show_trace_enable_, FLT_SHOW_TRACE_ENABLE))) { ret = OB_ERROR; } else { // fill type and len in the head int32_t total_len = *pos - org_pos - 6; if (OB_FAIL(flt_store_type_and_len(buf, len, &org_pos, control_info->type_, total_len))) { ret = OB_ERROR; } else { // do nothing } } return ret; } int flt_deserialize_field_controlinfo(FullLinkTraceExtraInfoId extra_id, const int64_t v_len, const char *buf, const int64_t len, int64_t *pos, void *flt_info) { int ret = OB_SUCCESS; FLTControlInfo *flt_control_info = (FLTControlInfo *)flt_info; switch(extra_id) { case FLT_LEVEL: { if (OB_FAIL(flt_get_int1(buf, len, pos, v_len, &flt_control_info->level_))) { ret = OB_ERROR; } else { // do nothing #ifdef DEBUG_OB20 printf("level is %hhd\n", flt_control_info->level_); #endif } break; } case FLT_SAMPLE_PERCENTAGE: { if (OB_FAIL(flt_get_double(buf, len, pos, v_len, &flt_control_info->sample_pct_))) { ret = OB_ERROR; } else { // do nothing #ifdef DEBUG_OB20 printf("sample_pct is %f\n", flt_control_info->sample_pct_); #endif } break; } case FLT_RECORD_POLICY: { int8_t v = 0; if (OB_FAIL(flt_get_int1(buf, len, pos, v_len, &v))) { ret = OB_ERROR; } else { flt_control_info->rp_ = v; #ifdef DEBUG_OB20 printf("rp is %d\n", flt_control_info->rp_); #endif } break; } case FLT_PRINT_SAMPLE_PCT: { if (OB_FAIL(flt_get_double(buf, len, pos, v_len, &flt_control_info->print_sample_pct_))) { ret = OB_ERROR; } else { // do nothing #ifdef DEBUG_OB20 printf("print_sample_pct is %f\n", flt_control_info->print_sample_pct_); #endif } break; } case FLT_SLOW_QUERY_THRES: { if (OB_FAIL(flt_get_int8(buf, len, pos, v_len, &flt_control_info->slow_query_threshold_))) { ret = OB_ERROR; } else { // do nothing #ifdef DEBUG_OB20 printf("slow_query_threshold is %ld\n", flt_control_info->slow_query_threshold_); #endif } break; } case FLT_SHOW_TRACE_ENABLE: { if (OB_FAIL(flt_get_int1(buf, len, pos, v_len, &flt_control_info->flt_show_trace_enable_))) { ret = OB_ERROR; } else { #ifdef DEBUG_OB20 printf("show_trace_enable is %hhd\n", flt_control_info->flt_show_trace_enable_); #endif } break; } default: { // 这里碰到不能识别的key直接跳过 *pos += *pos + v_len; break; } } return ret; } // for control info // for app info int flt_get_serialize_size_appinfo(int32_t *size, void *flt_info) { int ret = OB_SUCCESS; int32_t local_size = 0; FLTAppInfo *app_info = (FLTAppInfo *)flt_info; if (OB_NOT_NULL(app_info->identifier_)) { local_size += flt_get_store_str_size(strlen(app_info->identifier_)); } if (OB_NOT_NULL(app_info->module_)) { local_size += flt_get_store_str_size(strlen(app_info->module_)); } if (OB_NOT_NULL(app_info->action_)) { local_size += flt_get_store_str_size(strlen(app_info->action_)); } if (OB_NOT_NULL(app_info->client_info_)) { local_size += flt_get_store_str_size(strlen(app_info->client_info_)); } if (0 != local_size) { local_size += TYPE_LENGTH + LEN_LENGTH; } *size = local_size; return ret; } int flt_serialize_appinfo(char *buf, const int64_t len, int64_t *pos, void *flt_info) { int ret = OB_SUCCESS; int64_t org_pos = *pos; FLTAppInfo *app_info = (FLTAppInfo *)flt_info; // resrver for type and len if (*pos + 6 > len) { ret = OB_SIZE_OVERFLOW; } else { *pos += 6; } if (OB_FAIL(ret)) { // do nothing } else if (OB_NOT_NULL(app_info->identifier_) && OB_FAIL(flt_store_str(buf, len, pos, app_info->identifier_, strlen(app_info->identifier_), FLT_CLIENT_IDENTIFIER))) { ret = OB_ERROR; } else if (OB_NOT_NULL(app_info->module_) && OB_FAIL(flt_store_str(buf, len, pos, app_info->module_, strlen(app_info->module_), FLT_MODULE))) { ret = OB_ERROR; } else if (OB_NOT_NULL(app_info->action_) && OB_FAIL(flt_store_str(buf, len, pos, app_info->action_, strlen(app_info->action_), FLT_ACTION))) { ret = OB_ERROR; } else if (OB_NOT_NULL(app_info->client_info_) && OB_FAIL(flt_store_str(buf, len, pos, app_info->client_info_, strlen(app_info->client_info_), FLT_CLIENT_INFO))) { ret = OB_ERROR; } else { // fill type and len in the head int32_t total_len = *pos - org_pos - 6; if (OB_FAIL(flt_store_type_and_len(buf, len, &org_pos, app_info->type_, total_len))) { ret = OB_ERROR; } else { // do nothing } } return ret; } int flt_deserialize_field_appinfo(FullLinkTraceExtraInfoId extra_id, const int64_t v_len, const char *buf, const int64_t len, int64_t *pos, void *flt_info) { int ret = OB_SUCCESS; FLTAppInfo *app_info = (FLTAppInfo *)flt_info; switch(extra_id) { case FLT_CLIENT_IDENTIFIER: { if (OB_FAIL(flt_get_str(buf, len, pos, v_len, (char **)&app_info->identifier_))) { ret = OB_ERROR; } else { // do nothing } break; } case FLT_MODULE: { if (OB_FAIL(flt_get_str(buf, len, pos, v_len, (char **)&app_info->module_))) { ret = OB_ERROR; } else { // do nothing } break; } case FLT_ACTION: { if (OB_FAIL(flt_get_str(buf, len, pos, v_len, (char **)&app_info->action_))) { ret = OB_ERROR; } else { // do nothing } break; } case FLT_CLIENT_INFO: { if (OB_FAIL(flt_get_str(buf, len, pos, v_len, (char **)&app_info->client_info_))) { ret = OB_ERROR; } else { // do nothing } break; } default: { // get an unrecognized key here, skip it directly *pos += *pos + v_len; break; } } return ret; } // for app info // for queryinfo int flt_get_serialize_size_queryinfo(int32_t *size, void *flt_info) { int ret = OB_SUCCESS; int32_t local_size = 0; UNUSED(flt_info); local_size += TYPE_LENGTH + LEN_LENGTH; local_size += flt_get_store_int8_size(); local_size += flt_get_store_int8_size(); *size = local_size; return ret; } int flt_serialize_queryinfo(char *buf, const int64_t len, int64_t *pos, void *flt_info) { int ret = OB_SUCCESS; int64_t org_pos = *pos; FLTQueryInfo *query_info = (FLTQueryInfo *)flt_info; // resrver for type and len if (*pos + 6 > len) { ret = OB_SIZE_OVERFLOW; } else { *pos += 6; } if (OB_FAIL(ret)) { // do nothing } else if (OB_FAIL(flt_store_int8(buf, len, pos, query_info->query_start_timestamp_, FLT_QUERY_START_TIMESTAMP))) { ret = OB_ERROR; } else if (OB_FAIL(flt_store_int8(buf, len, pos, query_info->query_end_timestamp_, FLT_QUERY_END_TIMESTAMP))) { ret = OB_ERROR; } else { // fill type and len in the head int32_t total_len = *pos - org_pos - 6; if (OB_FAIL(flt_store_type_and_len(buf, len, &org_pos, query_info->type_, total_len))) { ret = OB_ERROR; } else { // do nothing } } return ret; } int flt_deserialize_field_queryinfo(FullLinkTraceExtraInfoId extra_id, const int64_t v_len, const char *buf, const int64_t len, int64_t *pos, void *flt_info) { int ret = OB_SUCCESS; FLTQueryInfo *query_info = (FLTQueryInfo *)flt_info; switch(extra_id) { case FLT_QUERY_START_TIMESTAMP: { if (OB_FAIL(flt_get_int8(buf, len, pos, v_len, &query_info->query_start_timestamp_))) { ret = OB_ERROR; } else { // do nothing } break; } case FLT_QUERY_END_TIMESTAMP: { if (OB_FAIL(flt_get_int8(buf, len, pos, v_len, &query_info->query_end_timestamp_))) { ret = OB_ERROR; } else { // do nothing } break; } default: { // get an unrecognized key here, skip it directly *pos += *pos + v_len; break; } } return ret; } // for queryinfo // for spaninfo int flt_get_serialize_size_spaninfo(int32_t *size, void *flt_info) { int ret = OB_SUCCESS; int32_t local_size = 0; FLTSpanInfo *span_info = (FLTSpanInfo *)flt_info; // FLTSpanInfo *span_info = (FLTSpanInfo *)flt_info; // If trace is enabled, other fields need to be sent if (TRUE == span_info->trace_enable_) { local_size += TYPE_LENGTH + LEN_LENGTH; local_size += flt_get_store_int1_size(); local_size += flt_get_store_int1_size(); local_size += flt_get_store_str_size(UUID4_SERIALIZE_LEN); local_size += flt_get_store_int1_size(); local_size += flt_get_store_str_size(UUID4_SERIALIZE_LEN); } *size = local_size; return ret; } int flt_serialize_spaninfo(char *buf, const int64_t len, int64_t *pos, void *flt_info) { int ret = OB_SUCCESS; int64_t org_pos = *pos; FLTSpanInfo *span_info = (FLTSpanInfo *)flt_info; // resrver for type and len if (TRUE == span_info->trace_enable_) { if (*pos + 6 > len) { ret = OB_SIZE_OVERFLOW; } else { *pos += 6; } if (OB_FAIL(ret)) { // do nothing } else if (OB_FAIL(flt_store_int1(buf, len, pos, span_info->trace_enable_, FLT_TRACE_ENABLE))) { ret = OB_ERROR; } else if (OB_FAIL(flt_store_int1(buf, len, pos, span_info->force_print_, FLT_FORCE_PRINT))) { ret = OB_ERROR; } else if (OB_FAIL(flt_store_str(buf, len, pos, span_info->trace_id_, UUID4_SERIALIZE_LEN, FLT_TRACE_ID))) { ret = OB_ERROR; } else if (OB_FAIL(flt_store_int1(buf, len, pos, span_info->ref_type_, FLT_REF_TYPE))) { ret = OB_ERROR; } else if (OB_FAIL(flt_store_str(buf, len, pos, span_info->span_id_, UUID4_SERIALIZE_LEN, FLT_SPAN_ID))) { ret = OB_ERROR; } else { // success } if (OB_SUCC(ret)) { // fill type and len in the head int32_t total_len = *pos - org_pos - 6; if (OB_FAIL(flt_store_type_and_len(buf, len, &org_pos, span_info->type_, total_len))) { ret = OB_ERROR; } else { // do nothing } } } return ret; } int flt_deserialize_field_spaninfo(FullLinkTraceExtraInfoId extra_id, const int64_t v_len, const char *buf, const int64_t len, int64_t *pos, void *flt_info) { int ret = OB_SUCCESS; FLTSpanInfo *span_info = (FLTSpanInfo *)flt_info; switch(extra_id) { case FLT_TRACE_ENABLE: { if (OB_FAIL(flt_get_int1(buf, len, pos, v_len, &span_info->trace_enable_))) { ret = OB_ERROR; } else { // do nothing } break; } case FLT_FORCE_PRINT: { if (OB_FAIL(flt_get_int1(buf, len, pos, v_len, &span_info->force_print_))) { ret = OB_ERROR; } else { // do nothing } break; } case FLT_TRACE_ID: { if (OB_FAIL(flt_get_str(buf, len, pos, v_len, (char **)&span_info->trace_id_))) { ret = OB_ERROR; } else { // do nothing } break; } case FLT_REF_TYPE: { if (OB_FAIL(flt_get_int1(buf, len, pos, v_len, &span_info->ref_type_))) { ret = OB_ERROR; } else { // do nothing } break; } case FLT_SPAN_ID: { if (OB_FAIL(flt_get_str(buf, len, pos, v_len, (char **)&span_info->span_id_))) { ret = OB_ERROR; } else { // do nothing } break; } default: { *pos += *pos + v_len; break; } } return ret; } // for spaninfo // for driverspaninfo info int flt_get_serialize_size_driverspaninfo(int32_t *size, void *flt_info) { int ret = OB_SUCCESS; int32_t local_size = 0; FLTDriverSpanInfo *client_info = (FLTDriverSpanInfo *)flt_info; if (NULL != client_info->client_span_) { local_size += TYPE_LENGTH + LEN_LENGTH; local_size += flt_get_store_str_size(strlen(client_info->client_span_) + 1); } *size = local_size; return ret; } int flt_serialize_driverspaninfo(char *buf, const int64_t len, int64_t *pos, void *flt_info) { int ret = OB_SUCCESS; int64_t org_pos = *pos; FLTDriverSpanInfo *client_info = (FLTDriverSpanInfo *)flt_info; // resrver for type and len if (*pos + 6 > len) { ret = OB_SIZE_OVERFLOW; } else { *pos += 6; } if (OB_FAIL(ret)) { // do nothing } else if (OB_FAIL(flt_store_str(buf, len, pos, client_info->client_span_, strlen(client_info->client_span_) + 1, FLT_DRIVER_SPAN))) { ret = OB_ERROR; } else { // fill type and len in the head int32_t total_len = *pos - org_pos - 6; if (OB_FAIL(flt_store_type_and_len(buf, len, &org_pos, client_info->type_, total_len))) { ret = OB_ERROR; } else { // do nothing } } return ret; } int flt_deserialize_field_driverspaninfo(FullLinkTraceExtraInfoId extra_id, const int64_t v_len, const char *buf, const int64_t len, int64_t *pos, void *flt_info) { int ret = OB_SUCCESS; FLTDriverSpanInfo *client_info = (FLTDriverSpanInfo *)flt_info; switch(extra_id) { case FLT_CLIENT_IDENTIFIER: { if (OB_FAIL(flt_get_str(buf, len, pos, v_len, (char **)&client_info->client_span_))) { ret = OB_ERROR; } else { // do nothing } break; } default: { *pos += *pos + v_len; break; } } return ret; } // for driverspaninfo info // for show trace span int flt_get_serialize_size_showtracespan(int32_t *size, void *flt_info) { int ret = OB_SUCCESS; int32_t local_size = 0; FLTShowTraceSpan *show_trace_span = (FLTShowTraceSpan *)flt_info; if (NULL != show_trace_span->client_span_json_) { local_size += TYPE_LENGTH + LEN_LENGTH; local_size += flt_get_store_str_size(strlen(show_trace_span->client_span_json_) + 1); } *size = local_size; return ret; } int flt_serialize_showtracespan(char *buf, const int64_t len, int64_t *pos, void *flt_info) { int ret = OB_SUCCESS; int64_t org_pos = *pos; FLTShowTraceSpan *show_trace_span = (FLTShowTraceSpan *)flt_info; // resrver for type and len if (*pos + 6 > len) { ret = OB_SIZE_OVERFLOW; } else { *pos += 6; } if (OB_FAIL(ret)) { // do nothing } else if (OB_FAIL(flt_store_str(buf, len, pos, show_trace_span->client_span_json_, strlen(show_trace_span->client_span_json_) + 1, FLT_DRV_SHOW_TRACE_SPAN))) { ret = OB_ERROR; } else { // fill type and len in the head int32_t total_len = *pos - org_pos - 6; if (OB_FAIL(flt_store_type_and_len(buf, len, &org_pos, show_trace_span->type_, total_len))) { ret = OB_ERROR; } else { // do nothing } } return ret; } int flt_deserialize_field_showtracespan(FullLinkTraceExtraInfoId extra_id, const int64_t v_len, const char *buf, const int64_t len, int64_t *pos, void *flt_info) { int ret = OB_SUCCESS; FLTShowTraceSpan *show_trace_span = (FLTShowTraceSpan *)flt_info; switch(extra_id) { case FLT_CLIENT_IDENTIFIER: { if (OB_FAIL(flt_get_str(buf, len, pos, v_len, (char **)&show_trace_span->client_span_json_))) { ret = OB_ERROR; } else { // do nothing } break; } default: { *pos += *pos + v_len; break; } } return ret; } // for driverspaninfo info // for no support int flt_deserialize_field_nosupport(FullLinkTraceExtraInfoId extra_id, const int64_t v_len, const char *buf, const int64_t len, int64_t *pos, void *flt_info) { UNUSED(extra_id); UNUSED(v_len); UNUSED(buf); UNUSED(len); UNUSED(pos); UNUSED(flt_info); return OB_ERROR; } int flt_serialize_nosupport(char *buf, const int64_t len, int64_t *pos, void *flt_info) { UNUSED(buf); UNUSED(len); UNUSED(pos); UNUSED(flt_info); return OB_ERROR; } int flt_get_serialize_size_nosupport(int32_t *size, void *flt_info) { UNUSED(size); UNUSED(flt_info); return OB_ERROR; } // for encode static int flt_store_int(char *buf, int64_t len, int64_t *ppos, int64_t v, int16_t type, int64_t v_len) { int ret = OB_SUCCESS; int64_t pos = *ppos; if (OB_ISNULL(buf)) { ret = OB_ERROR; } else if (len < pos + TYPE_LENGTH + LEN_LENGTH + v_len) { ret = OB_ERROR; } else { int2store(buf + pos, type); pos += 2; int4store(buf + pos, v_len); pos += 4; if (1 == v_len) { int1store(buf + pos, v); } else if (2 == v_len) { int2store(buf + pos, v); } else if (3 == v_len) { int3store(buf + pos, v); } else if (4 == v_len) { int4store(buf + pos, v); } else if (5 == v_len) { int5store(buf + pos, v); } else if (6 == v_len) { int6store(buf + pos, v); } else if (8 == v_len) { int8store(buf + pos, v); } pos += v_len; *ppos = pos; } return ret; } int flt_store_type_and_len(char *buf, int64_t len, int64_t *ppos, int16_t type, int32_t v_len) { int ret = OB_SUCCESS; int64_t pos = *ppos; if (OB_ISNULL(buf)) { ret = OB_ERROR; } else if (len < pos + TYPE_LENGTH + LEN_LENGTH) { ret = OB_ERROR; } else { int2store(buf + pos, type); pos += 2; int4store(buf + pos, v_len); pos += 4; *ppos = pos; } return ret; } int flt_store_str(char *buf, int64_t len, int64_t *ppos, const char *str, const uint64_t str_len, int16_t type) { int ret = OB_SUCCESS; int64_t pos = *ppos; if (OB_ISNULL(buf)) { ret = OB_ERROR; } else if (len < pos + TYPE_LENGTH + LEN_LENGTH + (int64_t)str_len) { ret = OB_ERROR; } else { int2store(buf + pos, type); pos += 2; int4store(buf + pos, str_len); pos += 4; memcpy(buf + pos, str, str_len); pos += str_len; *ppos = pos; } return ret; } int flt_store_int1(char *buf, int64_t len, int64_t *pos, int8_t v, int16_t type) { return flt_store_int(buf, len, pos, v, type, 1); } int flt_store_int2(char *buf, int64_t len, int64_t *pos, int16_t v, int16_t type) { return flt_store_int(buf, len, pos, v, type, 2); } int flt_store_int3(char *buf, int64_t len, int64_t *pos, int32_t v, int16_t type) { return flt_store_int(buf, len, pos, v, type, 3); } int flt_store_int4(char *buf, int64_t len, int64_t *pos, int32_t v, int16_t type) { return flt_store_int(buf, len, pos, v, type, 4); } int flt_store_int5(char *buf, int64_t len, int64_t *pos, int64_t v, int16_t type) { return flt_store_int(buf, len, pos, v, type, 5); } int flt_store_int6(char *buf, int64_t len, int64_t *pos, int64_t v, int16_t type) { return flt_store_int(buf, len, pos, v, type, 6); } int flt_store_int8(char *buf, int64_t len, int64_t *pos, int64_t v, int16_t type) { return flt_store_int(buf, len, pos, v, type, 7); } int flt_store_double(char *buf, const int64_t len, int64_t *ppos, double val, int16_t type) { int ret = OB_SUCCESS; int v_len = DBL_SIZE; int64_t pos = *ppos; if (OB_ISNULL(buf)) { ret = OB_ERROR; } else if ((uint64_t)len < pos + DBL_SIZE + TYPE_LENGTH + LEN_LENGTH) { ret = OB_ERROR; } else { int2store(buf + pos, type); pos += 2; int4store(buf + pos, v_len); pos += 4; memcpy(buf + pos, &val, DBL_SIZE); pos += DBL_SIZE; *ppos = pos; } return ret; } int flt_store_float(char *buf, const int64_t len, int64_t *ppos, float val, int16_t type) { int ret = OB_SUCCESS; int v_len = FLT_SIZE; int64_t pos = *ppos; if (OB_ISNULL(buf)) { ret = OB_ERROR; } else if ((uint64_t)len < pos + FLT_SIZE + TYPE_LENGTH + LEN_LENGTH) { ret = OB_ERROR; } else { int2store(buf + pos, type); pos += 2; int4store(buf + pos, v_len); pos += 4; memcpy(buf + pos, &val, FLT_SIZE); pos += FLT_SIZE; *ppos = pos; } return ret; } inline int flt_get_store_str_size(const uint64_t str_len) { return TYPE_LENGTH + LEN_LENGTH + str_len; } int flt_get_store_int1_size() { return TYPE_LENGTH + LEN_LENGTH + 1; } int flt_get_store_int2_size() { return TYPE_LENGTH + LEN_LENGTH + 2; } int flt_get_store_int3_size() { return TYPE_LENGTH + LEN_LENGTH + 3; } int flt_get_store_int4_size() { return TYPE_LENGTH + LEN_LENGTH + 4; } int flt_get_store_int5_size() { return TYPE_LENGTH + LEN_LENGTH + 5; } int flt_get_store_int6_size() { return TYPE_LENGTH + LEN_LENGTH + 6; } int flt_get_store_int8_size() { return TYPE_LENGTH + LEN_LENGTH + 8; } int flt_get_store_double_size() { return TYPE_LENGTH + LEN_LENGTH + DBL_SIZE; } int flt_get_store_float_size() { return TYPE_LENGTH + LEN_LENGTH + FLT_SIZE; } static int flt_get_int(const char *buf, int64_t len, int64_t *ppos, int64_t v_len, void *val) { int ret = OB_SUCCESS; int64_t pos = *ppos; if (OB_ISNULL(buf)) { ret = OB_ERROR; } else if (pos + v_len > len) { ret = OB_ERROR; } else { if (1 == v_len) { *(int8_t *)val = sint1korr(buf + pos); } else if (2 == v_len) { *(int16_t *)val = sint2korr(buf + pos); } else if (3 == v_len) { *(int32_t *)val = sint3korr(buf + pos); } else if (4 == v_len) { *(int32_t *)val = sint4korr(buf + pos); } else if (8 == v_len) { *(int64_t *)val = sint8korr(buf + pos); } pos += v_len; *ppos = pos; } return ret; } int flt_resolve_type_and_len(const char *buf, int64_t len, int64_t *ppos, int16_t *type, int32_t *v_len) { int ret = OB_SUCCESS; int64_t pos = *ppos; if (OB_ISNULL(buf)) { ret = OB_ERROR; } else if (pos + TYPE_LENGTH + LEN_LENGTH > len) { ret = OB_ERROR; } else { *type = sint2korr(buf + pos); pos += 2; *v_len = sint4korr(buf + pos); pos += 4; *ppos = pos; } return ret; } int flt_get_str(const char *buf, int64_t len, int64_t *ppos, int64_t str_len, char **str) { int ret = OB_SUCCESS; int64_t pos = *ppos; if (OB_ISNULL(buf)) { ret = OB_ERROR; } else if (pos + str_len > len) { ret = OB_ERROR; } else { *str = (char *)buf; pos += str_len; *ppos = pos; } return ret; } //@{ 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 ret = OB_SUCCESS; if (1 != v_len) { ret = OB_ERROR; } else { ret = flt_get_int(buf, len, pos, v_len, val); } return ret; } int flt_get_int2(const char *buf, int64_t len, int64_t *pos, int64_t v_len, int16_t *val) { int ret = OB_SUCCESS; if (2 != v_len) { ret = OB_ERROR; } else { ret = flt_get_int(buf, len, pos, v_len, val); } return ret; } int flt_get_int3(const char *buf, int64_t len, int64_t *pos, int64_t v_len, int32_t *val) { int ret = OB_SUCCESS; if (3 != v_len) { ret = OB_ERROR; } else { ret = flt_get_int(buf, len, pos, v_len, val); } return ret; } int flt_get_int4(const char *buf, int64_t len, int64_t *pos, int64_t v_len, int32_t *val) { int ret = OB_SUCCESS; if (4 != v_len) { ret = OB_ERROR; } else { ret = flt_get_int(buf, len, pos, v_len, val); } return ret; } int flt_get_int8(const char *buf, int64_t len, int64_t *pos, int64_t v_len, int64_t *val) { int ret = OB_SUCCESS; if (8 != v_len) { ret = OB_ERROR; } else { ret = flt_get_int(buf, len, pos, v_len, val); } return ret; } int flt_get_double(const char *buf, int64_t len, int64_t *ppos, int64_t v_len, double *val) { int ret = OB_SUCCESS; int64_t pos = *ppos; if (OB_ISNULL(buf)) { ret = OB_ERROR; } else if (pos + v_len > len || sizeof(double) != v_len) { ret = OB_ERROR; } else { *val = (*((double *)(buf + pos))); pos += v_len; *ppos = pos; } return ret; } int flt_get_float(const char *buf, int64_t len, int64_t *ppos, int64_t v_len, float *val) { int ret = OB_SUCCESS; int64_t pos = *ppos; if (OB_ISNULL(buf)) { ret = OB_ERROR; } else if (pos + v_len > len || sizeof(float) != v_len) { ret = OB_ERROR; } else { *val = (*((float *)(buf + pos))); pos += v_len; *ppos = pos; } return ret; } static uint64_t xorshift128plus(uint64_t *s) { uint64_t s1 = s[0]; const uint64_t s0 = s[1]; s[0] = s0; s1 ^= s1 << 23; s[1] = s1 ^ s0 ^ (s1 >> 18) ^ (s0 >> 5); return s[1] + s0; } int uuid4_init(uint64_t *seed, size_t seed_size) { #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) size_t res; FILE *fp = fopen("/dev/urandom", "rb"); if (!fp) { return OB_ERROR; } res = fread(seed, 1, seed_size, fp); fclose(fp); if ( res != seed_size ) { return OB_ERROR; } #elif defined(_WIN32) int res; HCRYPTPROV hCryptProv; res = CryptAcquireContext( &hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); if (!res) { return OB_ERROR; } res = CryptGenRandom(hCryptProv, (DWORD) seed_size, (PBYTE) seed); CryptReleaseContext(hCryptProv, 0); if (!res) { return OB_ERROR; } #else #error "unsupported platform" #endif return OB_SUCCESS; } OBCLIENT_UUID uuid4_generate(uint64_t *seed) { uint64_t word; OBCLIENT_UUID ret; /* get random */ word = xorshift128plus(seed); // word[1] = xorshift128plus(seed); ret.high_ = get_current_time_us(); ret.low_ = word; return ret; } ObTrace *get_trace_instance(FLTInfo *flt) { return flt->trace_; } int trace_init(FLTInfo *flt) { int index; int ret = OB_SUCCESS; if (OB_ISNULL(flt)) { ret = OB_ERROR; } else { ObTrace *trace = (ObTrace *)malloc(OBTRACE_DEFAULT_BUFFER_SIZE); if (OB_ISNULL(trace)) { // malloc error ret = OB_ERROR; } else { memset(trace, 0, sizeof(*trace)); trace->buffer_size_ = OBTRACE_DEFAULT_BUFFER_SIZE - sizeof(*trace); trace->log_buf_ = trace->data_; // size is MAX_TRACE_LOG_SIZE trace->show_trace_buf_ = trace->data_ + MAX_TRACE_LOG_SIZE; // size is MAX_TRACE_LOG_SIZE trace->flt_serialize_buf_ = trace->data_ + (2 * MAX_TRACE_LOG_SIZE); // size is MAX_FLT_SERIALIZE_SIZE trace->offset_ = INIT_OFFSET; trace->auto_flush_ = 1; trace->trace_enable_ = FALSE; trace->show_trace_enable_ = FALSE; trace->force_print_ = FALSE; trace->slow_query_print_ = FALSE; trace->root_span_id_.low_ = 0; trace->root_span_id_.high_ = 0; trace->flt = flt; flt->trace_ = trace; // set the starting parentheses trace->show_trace_buf_[0] = '['; trace->show_trace_buf_offset_ = 1; trace->free_tag_list_.data_ = NULL; trace->free_tag_list_.next_ = NULL; trace->free_tag_list_.tag_type_ = 0; for (index = 0; index < TAG_CACHE_COUNT; ++index) { ObTagCtx *tag = (ObTagCtx *)(trace->data_ + TAG_BUFFER_BEGIN + (index * sizeof(ObTagCtx))); tag->next_ = trace->free_tag_list_.next_; trace->free_tag_list_.next_ = tag; } for (index = 0; index < SPAN_CACHE_COUNT; ++index) { char *begin_addr = trace->data_ + SPAN_BUFFER_BEGIN + (index * (sizeof(LIST) + sizeof(ObSpanCtx))); LIST *list = (LIST *)begin_addr; list->data = (ObSpanCtx *)(begin_addr + sizeof(LIST)); trace->free_span_list_ = list_add(trace->free_span_list_, list); } if (OB_FAIL(uuid4_init(trace->uuid_random_seed, sizeof(trace->uuid_random_seed)))) { // init uuid seed error } } } return ret; } void trace_end(FLTInfo *flt) { if (OB_NOT_NULL(flt)) { free(flt->trace_); flt->trace_ = NULL; } return; } void begin_trace(ObTrace *trace) { if (OB_NOT_NULL(trace)) { FLTInfo *flt = trace->flt; if (OB_ISNULL(flt)) { // error, do not entable trace trace->trace_enable_ = FALSE; trace->show_trace_enable_ = FALSE; } else if (FALSE == flt_is_vaild(flt)) { // error, invalid trace trace->trace_enable_ = FALSE; trace->show_trace_enable_ = FALSE; } else if (TRUE == flt->control_info_.flt_show_trace_enable_) { // for show trace , always true trace->trace_enable_ = TRUE; trace->show_trace_enable_ = TRUE; } else { double trace_pct = flt_get_pct(trace->uuid_random_seed); trace->show_trace_enable_ = FALSE; if (trace_pct <= flt->control_info_.sample_pct_) { // trace enable trace->trace_enable_ = TRUE; } else { trace->trace_enable_ = FALSE; } } if (TRUE == trace->trace_enable_) { // todo : add interface to set trace id trace->trace_id_ = uuid4_generate(trace->uuid_random_seed); trace->level_ = flt->control_info_.level_; // If the trace hits, the subsequent calculation and printing strategy if (TRUE == flt->control_info_.flt_show_trace_enable_) { // for show trace , always true trace->force_print_ = TRUE; } else if (RP_ALL == flt->control_info_.rp_) { trace->force_print_ = TRUE; } else if (RP_SAMPLE_AND_SLOW_QUERY == flt->control_info_.rp_) { // Hit print samples need to print double print_pct = flt_get_pct(trace->uuid_random_seed); if (print_pct <= flt->control_info_.print_sample_pct_) { trace->force_print_ = TRUE; } else { trace->force_print_ = FALSE; } } else if (RP_ONLY_SLOW_QUERY == flt->control_info_.rp_) { trace->force_print_ = FALSE; } else { trace->force_print_ = FALSE; } } else { // Set the trace level to 0, subsequent spans will not be processed trace->level_ = 0; trace->force_print_ = FALSE; trace->trace_id_.low_ = 0; trace->trace_id_.high_ = 0; } #ifdef DEBUG_OB20 printf("trace enable is %d, force print is %d\n", trace->trace_enable_, trace->force_print_); #endif } } void end_trace(ObTrace *trace) { if (OB_NOT_NULL(trace)) { LIST *span_elem; ObSpanCtx *span; while(OB_NOT_NULL(trace->current_span_list_)) { span_elem = trace->current_span_list_; span = (ObSpanCtx *)span_elem->data; if (0 == span->end_ts_) { span->end_ts_ = get_current_time_us(); } // add all elem to free span list trace->current_span_list_ = list_delete(trace->current_span_list_, span_elem); trace->free_span_list_ = list_add(trace->free_span_list_, span_elem); } trace->offset_ = INIT_OFFSET; trace->policy_ = 0; trace->last_active_span_ = NULL; } } // used by slow query void flush_first_span(ObTrace *trace) { LIST *span_list; ObSpanCtx *span; int64_t pos = 0; int ret = OB_SUCCESS; if (OB_ISNULL(trace) || (0 == trace->trace_id_.low_ && 0 == trace->trace_id_.high_)) { // do nothing } else if (OB_ISNULL(span_list = trace->current_span_list_)) { // do nothing } else if (OB_ISNULL(span = (ObSpanCtx *)span_list->data)) { // do nothing } else { ObTagCtx *tag = span->tags_; my_bool first = TRUE; char buf[MAX_TRACE_LOG_SIZE]; pos = 0; INIT_SPAN(trace, span); while (OB_SUCC(ret) && OB_NOT_NULL(tag)) { if (pos + 10 >= MAX_TRACE_LOG_SIZE) { ret = OB_ERROR; } else { buf[pos++] = ','; if (first) { strcpy(buf + pos, "\"tags\":["); pos += 8; first = FALSE; } ret = tostring_ObTagCtx(buf, MAX_TRACE_LOG_SIZE, &pos, tag); tag = tag->next_; } } if (0 != pos) { if (pos + 1 < MAX_TRACE_LOG_SIZE) { buf[pos++] = ']'; buf[pos++] = 0; } else { buf[MAX_TRACE_LOG_SIZE - 2] = ']'; buf[MAX_TRACE_LOG_SIZE - 1] = 0; } } if (OB_SUCC(ret)) { INIT_SPAN(trace, span->source_span_); ret = snprintf(trace->log_buf_ + trace->log_buf_offset_, MAX_TRACE_LOG_SIZE - trace->log_buf_offset_, TRACE_PATTERN "%s}", UUID_TOSTRING(trace->trace_id_), "obclient", UUID_TOSTRING(span->span_id_), span->start_ts_, span->end_ts_, UUID_TOSTRING(OB_ISNULL(span->source_span_) ? trace->root_span_id_ : span->source_span_->span_id_), span->is_follow_ ? "true" : "false", buf); if (ret < 0 || trace->log_buf_offset_ + ret >= MAX_TRACE_LOG_SIZE) { ret = OB_ERROR; } else { trace->log_buf_offset_ += ret; ret = OB_SUCCESS; } } if (OB_SUCC(ret) && 0 != span->end_ts_) { // clear span and reset tag ObTagCtx *tag = span->tags_; while(OB_NOT_NULL(tag)) { ObTagCtx *free_tag = tag; tag = tag->next_; reset_tag(trace, span, free_tag); } span->tags_ = NULL; trace->current_span_list_ = list_delete(trace->current_span_list_, span_list); trace->free_span_list_ = list_add(trace->free_span_list_, span_list); } } } void flush_trace(ObTrace *trace) { LIST *span_elem; ObSpanCtx *span; int64_t pos = 0; int ret = OB_SUCCESS; int log_buf_len = 0; int show_trace_buf_len = 0; if (OB_ISNULL(trace) || (0 == trace->trace_id_.low_ && 0 == trace->trace_id_.high_)) { // do nothing } else if (OB_ISNULL(trace->current_span_list_)) { // do nothing } else { while (OB_NOT_NULL(trace->current_span_list_) && OB_SUCC(ret)) { span_elem = trace->current_span_list_; span = (ObSpanCtx *)span_elem->data; if (OB_NOT_NULL(span)) { ObTagCtx *tag = span->tags_; my_bool first = TRUE; char buf[MAX_TRACE_LOG_SIZE] = {0}; pos = 0; INIT_SPAN(trace, span); while (OB_SUCC(ret) && OB_NOT_NULL(tag)) { if (pos + 10 >= MAX_TRACE_LOG_SIZE) { ret = OB_ERROR; } else { buf[pos++] = ','; if (first) { strcpy(buf + pos, "\"tags\":["); pos += 8; first = FALSE; } ret = tostring_ObTagCtx(buf, MAX_TRACE_LOG_SIZE, &pos, tag); tag = tag->next_; } } if (0 != pos) { if (pos + 1 < MAX_TRACE_LOG_SIZE) { buf[pos++] = ']'; buf[pos++] = 0; } else { buf[MAX_TRACE_LOG_SIZE - 2] = ']'; buf[MAX_TRACE_LOG_SIZE - 1] = 0; } } if (OB_SUCC(ret)) { INIT_SPAN(trace, span->source_span_); log_buf_len = snprintf(trace->log_buf_ + trace->log_buf_offset_, MAX_TRACE_LOG_SIZE - trace->log_buf_offset_, TRACE_PATTERN "%s}", UUID_TOSTRING(trace->trace_id_), "obclient", UUID_TOSTRING(span->span_id_), span->start_ts_, span->end_ts_, UUID_TOSTRING(OB_ISNULL(span->source_span_) ? trace->root_span_id_ : span->source_span_->span_id_), span->is_follow_ ? "true" : "false", buf); if (log_buf_len < 0 || trace->log_buf_offset_ + log_buf_len >= MAX_TRACE_LOG_SIZE) { ret = OB_ERROR; } else { trace->log_buf_offset_ += log_buf_len; if (0 != span->end_ts_) { // The span that has ended needs to be put into the show trace buffer and sent to the backend next time show_trace_buf_len = snprintf(trace->show_trace_buf_ + trace->show_trace_buf_offset_, MAX_TRACE_LOG_SIZE - trace->show_trace_buf_offset_, "%.*s,", log_buf_len, trace->log_buf_ + trace->log_buf_offset_ - log_buf_len); if (show_trace_buf_len < 0 || trace->show_trace_buf_offset_ + show_trace_buf_len >= MAX_TRACE_LOG_SIZE) { ret = OB_ERROR; } else { trace->show_trace_buf_offset_ += show_trace_buf_len; } } } } if (OB_SUCC(ret) && 0 != span->end_ts_) { // clear span and reset tag ObTagCtx *tag = span->tags_; while(OB_NOT_NULL(tag)) { ObTagCtx *free_tag = tag; tag = tag->next_; reset_tag(trace, span, free_tag); } span->tags_ = 0; trace->current_span_list_ = list_delete(trace->current_span_list_, span_elem); trace->free_span_list_ = list_add(trace->free_span_list_, span_elem); } } } trace->offset_ = INIT_OFFSET; } } ObSpanCtx* begin_span(ObTrace *trace, uint32_t span_type, uint8_t level, my_bool is_follow) { ObSpanCtx *new_span = NULL; #ifdef DEBUG_OB20 printf("//////////////////////call begin_span ////////////////////////////////\n"); #endif if (OB_ISNULL(trace)) { // do nothing } else if (trace->trace_id_.low_ == 0 && trace->trace_id_.high_ == 0) { // trace is not enable } else if (level > trace->level_) { // do nothing } else { if (OB_ISNULL(trace->free_span_list_)) { FLUSH_TRACE(trace->flt); } if (OB_NOT_NULL(trace->free_span_list_)) { LIST *span_elem = trace->free_span_list_; if (OB_NOT_NULL(span_elem)) { new_span = (ObSpanCtx *)span_elem->data; new_span->span_type_ = span_type; new_span->span_id_.high_ = 0; new_span->span_id_.low_ = ++trace->seq_; new_span->source_span_ = trace->last_active_span_; new_span->is_follow_ = is_follow; new_span->start_ts_ = get_current_time_us(); new_span->end_ts_ = 0; new_span->tags_ = NULL; trace->last_active_span_ = new_span; trace->free_span_list_ = list_delete(trace->free_span_list_, span_elem); trace->current_span_list_ = list_add(trace->current_span_list_, span_elem); } } } return new_span; } void end_span(ObTrace *trace, ObSpanCtx *span) { #ifdef DEBUG_OB20 printf("//////////////////////call end_span ////////////////////////////////\n"); #endif if (OB_ISNULL(trace) || OB_ISNULL(trace->flt) || OB_ISNULL(span)) { // error } else if ((trace->trace_id_.low_ == 0 && trace->trace_id_.high_ == 0) || (span->span_id_.low_ == 0 && span->span_id_.high_ == 0)) { // trace id or span id is not inited } else { FLTInfo *flt = trace->flt; int64_t slow_query_threshold = flt->control_info_.slow_query_threshold_; int64_t use_time; RecordPolicy rp = flt->control_info_.rp_; span->end_ts_ = get_current_time_us(); use_time = span->end_ts_ - span->start_ts_; trace->last_active_span_ = span->source_span_; // The current driver has only one span, so directly calculate the end time of this span and then calculate the slow query // todo: Check the type of the span, only interactive spans need to record slow queries if (RP_ONLY_SLOW_QUERY == rp || RP_SAMPLE_AND_SLOW_QUERY == rp) { if (slow_query_threshold != -1 && slow_query_threshold <= use_time) { // If you find slow queries, you only need to enable log printing, and send the span log to the server for printing. #ifdef DEBUG_OB20 printf("get slow query, use_time is %ld, slow_query_threshold is %ld\n", use_time, slow_query_threshold); #endif trace->slow_query_print_ = TRUE; } } #ifdef DEBUG_OB20 printf("end span spanid:[%lu:%lu]\n", span->span_id_.high_, span->span_id_.low_); #endif } } void reset_span(ObTrace *trace) { if (OB_ISNULL(trace) || OB_ISNULL(trace->flt)) { // error } else if (trace->trace_id_.low_ == 0 && trace->trace_id_.high_ == 0) { // trace is not inited } else { ObSpanCtx *span; LIST *span_elem; while(OB_NOT_NULL(trace->current_span_list_)) { span_elem = trace->current_span_list_; span = (ObSpanCtx *)span_elem->data; // All spans are recycled after a statement in the transaction ends trace->current_span_list_ = list_delete(trace->current_span_list_, span_elem); trace->free_span_list_ = list_add(trace->free_span_list_, span_elem); span->tags_ = NULL; } } } void append_tag(ObTrace *trace, ObSpanCtx *span, uint16_t tag_type, const char *str) { if (OB_ISNULL(trace)) { // do nothing } else if (OB_ISNULL(str)) { // do nothing } else if (OB_ISNULL(trace->free_tag_list_.next_)) { // do nothing } else { // get tag from free tag list ObTagCtx *tag = (ObTagCtx *)(trace->free_tag_list_.next_); trace->free_tag_list_.next_ = tag->next_; // append tag into span tag->next_ = span->tags_; span->tags_ = tag; tag->tag_type_ = tag_type; tag->data_ = str; } } void reset_tag(ObTrace *trace, ObSpanCtx *span, ObTagCtx *tag) { UNUSED(span); if (OB_ISNULL(trace)) { // do nothing } else if (OB_ISNULL(tag)) { // do nothing } else { tag->next_ = trace->free_tag_list_.next_; trace->free_tag_list_.next_ = tag; } } int serialize_UUID(char *buf, const int64_t buf_len, int64_t *pos, OBCLIENT_UUID *uuid) { int ret = OB_SUCCESS; if (OB_FAIL(encode_i64(buf, buf_len, pos, uuid->high_))) { // LOG_WARN("deserialize failed", K(ret), K(buf), K(buf_len), K(pos)); } else if (OB_FAIL(encode_i64(buf, buf_len, pos, uuid->low_))) { // LOG_WARN("deserialize failed", K(ret), K(buf), K(buf_len), K(pos)); } return ret; } int deserialize_UUID(const char *buf, const int64_t buf_len, int64_t *pos, OBCLIENT_UUID *uuid) { int ret = OB_SUCCESS; if (OB_FAIL(decode_i64(buf, buf_len, pos, (int64_t *)(&uuid->high_)))) { // LOG_WARN("deserialize failed", K(ret), K(buf), K(buf_len), K(pos)); } else if (OB_FAIL(decode_i64(buf, buf_len, pos, (int64_t *)(&uuid->low_)))) { // LOG_WARN("deserialize failed", K(ret), K(buf), K(buf_len), K(pos)); } return ret; } DEFINE_TO_STRING_FUNC_FOR(OBCLIENT_UUID) { int ret = OB_SUCCESS; int64_t tmp_pos = *pos; const char *transfer = "0123456789abcdef"; if (tmp_pos + 37 > buf_len) { ret = OB_ERROR; } else { buf[tmp_pos++] = transfer[src->high_ >> 60 & 0xf]; buf[tmp_pos++] = transfer[src->high_ >> 56 & 0xf]; buf[tmp_pos++] = transfer[src->high_ >> 52 & 0xf]; buf[tmp_pos++] = transfer[src->high_ >> 48 & 0xf]; buf[tmp_pos++] = transfer[src->high_ >> 44 & 0xf]; buf[tmp_pos++] = transfer[src->high_ >> 40 & 0xf]; buf[tmp_pos++] = transfer[src->high_ >> 36 & 0xf]; buf[tmp_pos++] = transfer[src->high_ >> 32 & 0xf]; buf[tmp_pos++] = '-'; buf[tmp_pos++] = transfer[src->high_ >> 28 & 0xf]; buf[tmp_pos++] = transfer[src->high_ >> 24 & 0xf]; buf[tmp_pos++] = transfer[src->high_ >> 20 & 0xf]; buf[tmp_pos++] = transfer[src->high_ >> 16 & 0xf]; buf[tmp_pos++] = '-'; buf[tmp_pos++] = transfer[src->high_ >> 12 & 0xf]; buf[tmp_pos++] = transfer[src->high_ >> 8 & 0xf]; buf[tmp_pos++] = transfer[src->high_ >> 4 & 0xf]; buf[tmp_pos++] = transfer[src->high_ >> 0 & 0xf]; buf[tmp_pos++] = '-'; buf[tmp_pos++] = transfer[src->low_ >> 60 & 0xf]; buf[tmp_pos++] = transfer[src->low_ >> 56 & 0xf]; buf[tmp_pos++] = transfer[src->low_ >> 52 & 0xf]; buf[tmp_pos++] = transfer[src->low_ >> 48 & 0xf]; buf[tmp_pos++] = '-'; buf[tmp_pos++] = transfer[src->low_ >> 44 & 0xf]; buf[tmp_pos++] = transfer[src->low_ >> 40 & 0xf]; buf[tmp_pos++] = transfer[src->low_ >> 36 & 0xf]; buf[tmp_pos++] = transfer[src->low_ >> 32 & 0xf]; buf[tmp_pos++] = transfer[src->low_ >> 28 & 0xf]; buf[tmp_pos++] = transfer[src->low_ >> 24 & 0xf]; buf[tmp_pos++] = transfer[src->low_ >> 20 & 0xf]; buf[tmp_pos++] = transfer[src->low_ >> 16 & 0xf]; buf[tmp_pos++] = transfer[src->low_ >> 12 & 0xf]; buf[tmp_pos++] = transfer[src->low_ >> 8 & 0xf]; buf[tmp_pos++] = transfer[src->low_ >> 4 & 0xf]; buf[tmp_pos++] = transfer[src->low_ >> 0 & 0xf]; buf[tmp_pos ] = '\0'; } *pos = tmp_pos; return ret; } DEFINE_TO_STRING_FUNC_FOR(ObTagCtx) { int ret = OB_SUCCESS; char from[] = "\"\n\r\\"; const char *to[] = { "\\\"", "\\n", "\\r", "\\\\"}; int l = strlen(tag_str[src->tag_type_]); int64_t tmp_pos = *pos; const char *c = src->data_; const char *toc; my_bool conv = FALSE; int i; if (tmp_pos + l + 7 >= buf_len) { buf[buf_len - 1] = '\0'; ret = OB_ERROR; } else { buf[tmp_pos++] = '{'; buf[tmp_pos++] = '\"'; strcpy(buf + tmp_pos, tag_str[src->tag_type_]); tmp_pos += l; buf[tmp_pos++] = '\"'; buf[tmp_pos++] = ':'; buf[tmp_pos] = '\0'; for (; *c; ++c) { if (c != src->data_ && *(c + 1)) { // ignore the first one and the last one for (i = 0; i < 4; ++i) { if (from[i] == *c) { for (toc = to[i]; *toc; ++toc) { if (tmp_pos < buf_len) { buf[tmp_pos++] = *toc; } else { ret = OB_ERROR; } } conv = TRUE; break; } } } if (!conv && tmp_pos < buf_len) { buf[tmp_pos++] = *c; } } } if (OB_FAIL(ret) || tmp_pos + 1 >= buf_len) { buf[buf_len - 1] = 0; } else { buf[tmp_pos++] = '}'; buf[tmp_pos] = 0; } if (OB_SUCC(ret)) { *pos = tmp_pos; } return ret; } // DEFINE_TO_STRING_FUNC_FOR(ObSpanCtx) // { // int ret = 0; // char span_id[UUID4_LEN]; // char source_span_id[UUID4_LEN] = {0}; // int64_t span_id_pos = 0; // int64_t source_span_id_pos = 0; // if (OB_FAIL(tostring_UUID(span_id, UUID4_LEN, &span_id_pos, &src->span_id_))) { // // error // } else if (OB_NOT_NULL(src->source_span_id_) && (tostring_UUID(source_span_id, UUID4_LEN, &source_span_id_pos, src->source_span_id_))) { // // error // } else { // ret = snprintf(buf + *pos, buf_len - *pos, // "\"name\":\"%s\",\"id\":\"%s\",\"start_ts\":%ld,\"end_ts\":%ld,\"parent_id\":\"%s\",\"is_follow\":%s", // "ObClient", // span_id, // src->start_ts_, // src->end_ts_, // source_span_id, // src->is_follow_ ? "true" : "false"); // if (ret < 0 || *pos + ret >= buf_len) { // ret = OB_ERROR; // } else { // ObTagCtx* tag = src->tags_; // *pos = *pos + ret; // ret = OB_SUCCESS; // while (OB_SUCC(ret) && OB_NOT_NULL(tag)) { // ret = snprintf(buf + *pos, buf_len - *pos, ","); // if (ret < 0 || *pos + ret >= buf_len) { // ret = OB_ERROR; // } else { // *pos = *pos + ret; // ret = tostring_ObTagCtx(buf, buf_len, pos, tag); // tag = tag->next_; // } // } // } // } // return ret; // } int flt_set_module(MYSQL *mysql, const char *module_name) { int ret = 0; if (OB_ISNULL(mysql) || FALSE == get_use_full_link_trace(mysql)) { // error ret = 1; } else if (OB_ISNULL(mysql->net.ob20protocol)) { ret = 1; } else { FLTInfo *flt = mysql->net.ob20protocol->flt; if (OB_ISNULL(flt)) { ret = 1; } else { flt->app_info_.module_ = module_name; } } return ret; } int flt_set_action(MYSQL *mysql, const char *action_name) { int ret = 0; if (OB_ISNULL(mysql) || FALSE == get_use_full_link_trace(mysql)) { // error ret = 1; } else if (OB_ISNULL(mysql->net.ob20protocol)) { ret = 1; } else { FLTInfo *flt = mysql->net.ob20protocol->flt; if (OB_ISNULL(flt)) { ret = 1; } else { flt->app_info_.action_ = action_name; } } return ret; } int flt_set_client_info(MYSQL *mysql, const char *client_info) { int ret = 0; if (OB_ISNULL(mysql) || FALSE == get_use_full_link_trace(mysql)) { // error ret = 1; } else if (OB_ISNULL(mysql->net.ob20protocol)) { ret = 1; } else { FLTInfo *flt = mysql->net.ob20protocol->flt; if (OB_ISNULL(flt)) { ret = 1; } else { flt->app_info_.client_info_ = client_info; } } return ret; } int flt_set_identifier(MYSQL *mysql, const char *identifier) { int ret = 0; if (OB_ISNULL(mysql) || FALSE == get_use_full_link_trace(mysql)) { // error ret = 1; } else if (OB_ISNULL(mysql->net.ob20protocol)) { ret = 1; } else { FLTInfo *flt = mysql->net.ob20protocol->flt; if (OB_ISNULL(flt)) { ret = 1; } else { flt->app_info_.identifier_ = identifier; } } return ret; } int flt_get_control_level(MYSQL *mysql, int *level) { int ret = 0; if (OB_ISNULL(mysql) || FALSE == get_use_full_link_trace(mysql)) { // error ret = 1; } else if (OB_ISNULL(mysql->net.ob20protocol)) { ret = 1; } else { FLTInfo *flt = mysql->net.ob20protocol->flt; if (OB_ISNULL(flt)) { ret = 1; } else { *level = flt->control_info_.level_; } } return ret; } int flt_get_control_sample_pct(MYSQL *mysql, double *sample_pct) { int ret = 0; if (OB_ISNULL(mysql) || FALSE == get_use_full_link_trace(mysql)) { // error ret = 1; } else if (OB_ISNULL(mysql->net.ob20protocol)) { ret = 1; } else { FLTInfo *flt = mysql->net.ob20protocol->flt; if (OB_ISNULL(flt)) { ret = 1; } else { *sample_pct = flt->control_info_.sample_pct_; } } return ret; } int flt_get_control_record_policy(MYSQL *mysql, int *rp) { int ret = 0; if (OB_ISNULL(mysql) || FALSE == get_use_full_link_trace(mysql)) { // error ret = 1; } else if (OB_ISNULL(mysql->net.ob20protocol)) { ret = 1; } else { FLTInfo *flt = mysql->net.ob20protocol->flt; if (OB_ISNULL(flt)) { ret = 1; } else { *rp = flt->control_info_.rp_; } } return ret; } int flt_get_control_print_spct(MYSQL *mysql, double *sample_pct) { int ret = 0; if (OB_ISNULL(mysql) || FALSE == get_use_full_link_trace(mysql)) { // error ret = 1; } else if (OB_ISNULL(mysql->net.ob20protocol)) { ret = 1; } else { FLTInfo *flt = mysql->net.ob20protocol->flt; if (OB_ISNULL(flt)) { ret = 1; } else { *sample_pct = flt->control_info_.print_sample_pct_; } } return ret; } int flt_get_control_slow_threshold(MYSQL *mysql, long int *slow_threshold) { int ret = 0; if (OB_ISNULL(mysql) || FALSE == get_use_full_link_trace(mysql)) { // error ret = 1; } else if (OB_ISNULL(mysql->net.ob20protocol)) { ret = 1; } else { FLTInfo *flt = mysql->net.ob20protocol->flt; if (OB_ISNULL(flt)) { ret = 1; } else { *slow_threshold = flt->control_info_.slow_query_threshold_; } } return ret; }