226 lines
7.5 KiB
C++
226 lines
7.5 KiB
C++
// Copyright 2010-2016 Alibaba Inc. All Rights Reserved.
|
|
// Author:
|
|
//
|
|
// Normalizer:
|
|
//
|
|
// this file defines implementation of full link trace span manager
|
|
|
|
|
|
#define USING_LOG_PREFIX SERVER
|
|
|
|
#include "sql/monitor/flt/ob_flt_span_mgr.h"
|
|
#include "share/ob_define.h"
|
|
#include "lib/time/ob_time_utility.h"
|
|
#include "lib/allocator/ob_malloc.h"
|
|
#include "lib/allocator/ob_concurrent_fifo_allocator.h"
|
|
#include "lib/allocator/page_arena.h"
|
|
#include "lib/stat/ob_session_stat.h"
|
|
#include "lib/alloc/alloc_func.h"
|
|
#include "lib/thread/thread_mgr.h"
|
|
#include "lib/rc/ob_rc.h"
|
|
#include "share/rc/ob_context.h"
|
|
#include "observer/ob_server.h"
|
|
#include "sql/session/ob_basic_session_info.h"
|
|
#include "lib/trace/ob_trace.h"
|
|
|
|
namespace oceanbase
|
|
{
|
|
using namespace oceanbase::share::schema;
|
|
namespace sql
|
|
{
|
|
ObFLTSpanMgr* get_flt_span_manager() {
|
|
return MTL(ObFLTSpanMgr*);
|
|
}
|
|
|
|
int ObFLTSpanMgr::init(uint64_t tenant_id, const int64_t max_mem_size, const int64_t queue_size)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (inited_) {
|
|
ret = OB_INIT_TWICE;
|
|
} else if (OB_FAIL(queue_.init("SqlFltSpanRec", queue_size, tenant_id))) {
|
|
SERVER_LOG(WARN, "Failed to init ObMySQLRequestQueue", K(ret));
|
|
} else if (OB_FAIL(TG_CREATE_TENANT(lib::TGDefIDs::ReqMemEvict, tg_id_))) {
|
|
SERVER_LOG(WARN, "create failed", K(ret));
|
|
} else if (OB_FAIL(TG_START(tg_id_))) {
|
|
SERVER_LOG(WARN, "init timer fail", K(ret));
|
|
} else if (OB_FAIL(allocator_.init(FLT_SPAN_PAGE_SIZE,
|
|
"SqlFltSpanRec",
|
|
tenant_id,
|
|
INT64_MAX))) {
|
|
SERVER_LOG(WARN, "failed to init allocator", K(ret));
|
|
} else {
|
|
mem_limit_ = max_mem_size;
|
|
tenant_id_ = tenant_id;
|
|
inited_ = true;
|
|
destroyed_ = false;
|
|
}
|
|
if ((OB_FAIL(ret)) && (!inited_)) {
|
|
destroy();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void ObFLTSpanMgr::destroy()
|
|
{
|
|
if (!destroyed_) {
|
|
TG_DESTROY(tg_id_);
|
|
clear_queue();
|
|
queue_.destroy();
|
|
allocator_.destroy();
|
|
inited_ = false;
|
|
destroyed_ = true;
|
|
}
|
|
}
|
|
|
|
int ObFLTSpanMgr::mtl_init(ObFLTSpanMgr* &span_mgr)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
span_mgr = OB_NEW(ObFLTSpanMgr, "SqlFltSpanRec");
|
|
if (nullptr == span_mgr) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
LOG_WARN("failed to alloc memory for ObMySQLRequestManager", K(ret));
|
|
} else {
|
|
uint64_t tenant_id = lib::current_resource_owner_id();
|
|
int64_t mem_limit = lib::get_tenant_memory_limit(tenant_id);
|
|
int64_t queue_size = MAX_QUEUE_SIZE;
|
|
if (OB_FAIL(span_mgr->init(tenant_id, mem_limit, queue_size))) {
|
|
LOG_WARN("failed to init request manager", K(ret));
|
|
} else {
|
|
// do nothing
|
|
}
|
|
}
|
|
if (OB_FAIL(ret) && span_mgr != nullptr) {
|
|
// cleanup
|
|
common::ob_delete(span_mgr);
|
|
span_mgr = nullptr;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void ObFLTSpanMgr::mtl_destroy(ObFLTSpanMgr* &span_mgr)
|
|
{
|
|
common::ob_delete(span_mgr);
|
|
span_mgr = nullptr;
|
|
}
|
|
|
|
|
|
int ObFLTSpanMgr::record_span(ObFLTSpanData &span_data, bool is_formmated_json)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!inited_) {
|
|
ret = OB_NOT_INIT;
|
|
} else {
|
|
ObFLTSpanRec *rec = NULL;
|
|
char *buf = NULL;
|
|
//alloc mem from allocator
|
|
int64_t pos = sizeof(ObFLTSpanRec);
|
|
int64_t total_sz = sizeof(ObFLTSpanRec)
|
|
+ min(span_data.trace_id_.length(), OB_MAX_SPAN_LENGTH)
|
|
+ min(span_data.span_id_.length(), OB_MAX_SPAN_LENGTH)
|
|
+ min(span_data.parent_span_id_.length(), OB_MAX_SPAN_LENGTH)
|
|
+ min(span_data.span_name_.length(), OB_MAX_SPAN_LENGTH)
|
|
+ min(span_data.tags_.length(), OB_MAX_SPAN_TAG_LENGTH)
|
|
+ min(span_data.logs_.length(), OB_MAX_SPAN_TAG_LENGTH)
|
|
+ (is_formmated_json ? 0:4);
|
|
if (NULL == (buf = (char*)allocator_.alloc(total_sz))) {
|
|
ret = OB_ALLOCATE_MEMORY_FAILED;
|
|
if (REACH_TIME_INTERVAL(100 * 1000)) {
|
|
SERVER_LOG(WARN, "record concurrent fifoallocator alloc mem failed", K(sizeof(ObFLTSpanRec)), K(ret));
|
|
}
|
|
} else {
|
|
rec = new(buf)ObFLTSpanRec();
|
|
rec->allocator_ = &allocator_;
|
|
rec->data_ = span_data;
|
|
//deep copy trace id
|
|
if (!span_data.trace_id_.empty()) {
|
|
const int len = min(span_data.trace_id_.length(), OB_MAX_SPAN_LENGTH);
|
|
MEMCPY(buf + pos, span_data.trace_id_.ptr(), len);
|
|
rec->data_.trace_id_.assign_ptr(buf + pos, len);
|
|
pos += len;
|
|
}
|
|
//deep copy span id
|
|
if (!span_data.span_id_.empty()) {
|
|
const int len = min(span_data.span_id_.length(), OB_MAX_SPAN_LENGTH);
|
|
MEMCPY(buf + pos, span_data.span_id_.ptr(), len);
|
|
rec->data_.span_id_.assign_ptr(buf + pos, len);
|
|
pos += len;
|
|
}
|
|
//deep copy parent span id
|
|
if (!span_data.parent_span_id_.empty()) {
|
|
const int len = min(span_data.parent_span_id_.length(), OB_MAX_SPAN_LENGTH);
|
|
MEMCPY(buf + pos, span_data.parent_span_id_.ptr(), len);
|
|
rec->data_.parent_span_id_.assign_ptr(buf + pos, len);
|
|
pos += len;
|
|
}
|
|
//deep copy span name
|
|
if (!span_data.span_name_.empty()) {
|
|
const int len = min(span_data.span_name_.length(), OB_MAX_SPAN_LENGTH);
|
|
MEMCPY(buf + pos, span_data.span_name_.ptr(), len);
|
|
rec->data_.span_name_.assign_ptr(buf + pos, len);
|
|
pos += len;
|
|
}
|
|
//deep copy tags
|
|
if (!span_data.tags_.empty()) {
|
|
const int len = min(span_data.tags_.length(), OB_MAX_SPAN_TAG_LENGTH);
|
|
if (is_formmated_json) {
|
|
MEMCPY(buf + pos, span_data.tags_.ptr(), len);
|
|
rec->data_.tags_.assign_ptr(buf + pos, len);
|
|
pos += len;
|
|
} else {
|
|
buf[pos] = '[';
|
|
MEMCPY(buf + pos + 1, span_data.tags_.ptr(), len);
|
|
buf[pos + len + 1] = ']';
|
|
rec->data_.tags_.assign_ptr(buf + pos, len + 2);
|
|
pos += len + 2;
|
|
}
|
|
}
|
|
//deep copy logs_
|
|
if (!span_data.logs_.empty()) {
|
|
const int len = min(span_data.logs_.length(), OB_MAX_SPAN_TAG_LENGTH);
|
|
if (is_formmated_json) {
|
|
MEMCPY(buf + pos, span_data.logs_.ptr(), len);
|
|
rec->data_.logs_.assign_ptr(buf + pos, len);
|
|
pos += len;
|
|
} else {
|
|
buf[pos] = '[';
|
|
MEMCPY(buf + pos + 1, span_data.logs_.ptr(), len);
|
|
buf[pos + len + 1] = ']';
|
|
rec->data_.logs_.assign_ptr(buf + pos, len + 2);
|
|
pos += len + 2;
|
|
}
|
|
}
|
|
//push into queue
|
|
if (OB_SUCC(ret)) {
|
|
int64_t req_id = 0;
|
|
if (OB_FAIL(queue_.push(rec, req_id))) {
|
|
//sql audit槽位已满时会push失败, 依赖后台线程进行淘汰获得可用槽位
|
|
if (REACH_TIME_INTERVAL(2 * 1000 * 1000)) {
|
|
SERVER_LOG(WARN, "push into queue failed", K(ret));
|
|
}
|
|
allocator_.free(rec);
|
|
rec = NULL;
|
|
} else {
|
|
rec->data_.req_id_ = req_id;
|
|
}
|
|
} else {
|
|
allocator_.free(rec);
|
|
rec = NULL;
|
|
}
|
|
}
|
|
} // end
|
|
return ret;
|
|
}
|
|
|
|
// evict old span and release memory
|
|
int ObFLTSpanMgr::release_old(int64_t limit)
|
|
{
|
|
void * span = NULL;
|
|
int64_t count = 0;
|
|
while(count++ < limit && NULL != (span = queue_.pop())) {
|
|
free(span);
|
|
}
|
|
return common::OB_SUCCESS;
|
|
}
|
|
} // end of namespace obmysql
|
|
} // end of namespace oceanbase
|