in src/brpc/builtin/rpcz_service.cpp [490:698]
void RpczService::default_method(::google::protobuf::RpcController* cntl_base,
const ::brpc::RpczRequest*,
::brpc::RpczResponse*,
::google::protobuf::Closure* done) {
ClosureGuard done_guard(done);
Controller *cntl = static_cast<Controller*>(cntl_base);
uint64_t trace_id = 0;
const bool use_html = UseHTML(cntl->http_request());
cntl->http_response().set_content_type(
use_html ? "text/html" : "text/plain");
butil::IOBufBuilder os;
if (use_html) {
os << "<!DOCTYPE html><html><head>\n"
<< "<script language=\"javascript\" type=\"text/javascript\" src=\"/js/jquery_min\"></script>\n"
<< TabsHead()
<< "</head><body>";
cntl->server()->PrintTabsBody(os, "rpcz");
}
if (!FLAGS_enable_rpcz && !has_span_db()) {
if (use_html) {
os << "<input type='button' "
"onclick='location.href=\"/rpcz/enable\";' value='enable' />"
" rpcz to track recent RPC calls with small overhead, "
"you can turn it off at any time.";
} else {
os << "rpcz is not enabled yet. You can turn on/off rpcz by accessing "
"/rpcz/enable and /rpcz/disable respectively.";
}
os.move_to(cntl->response_attachment());
return;
}
butil::EndPoint my_addr(butil::my_ip(),
cntl->server()->listen_address().port);
const std::string* trace_id_str =
cntl->http_request().uri().GetQuery(TRACE_ID_STR);
if (trace_id_str) {
char* endptr;
trace_id = strtoull(trace_id_str->c_str(), &endptr, 16);
if (*endptr != '\0') {
trace_id = 0;
}
}
if (trace_id != 0) { // Point search
uint64_t span_id = 0;
const std::string* span_id_str =
cntl->http_request().uri().GetQuery(SPAN_ID_STR);
if (span_id_str) {
char* endptr;
span_id = strtoull(span_id_str->c_str(), &endptr, 16);
if (*endptr != '\0') {
span_id = 0;
}
}
std::deque<RpczSpan> spans;
if (span_id == 0) {
FindSpans(trace_id, &spans);
std::sort(spans.begin(), spans.end(), CompareByStartRealTime());
} else {
spans.resize(1);
if (FindSpan(trace_id, span_id, &spans[0]) != 0) {
spans.clear();
}
}
if (spans.empty()) {
os << "Fail to find any spans"
<< (use_html ? "</body></html>" : "");
os.move_to(cntl->response_attachment());
return;
}
if (use_html) {
os << "<pre>\n";
}
for (size_t i = 0; i < spans.size(); ++i) {
RpczSpan& span = spans[i];
if (span.type() == SPAN_TYPE_SERVER) {
PrintServerSpan(os, span, use_html);
} else {
PrintClientSpan(os, span, use_html);
}
os << std::endl;
}
if (use_html) {
os << "</pre></body></html>";
}
os.move_to(cntl->response_attachment());
return;
} else {
const std::string* time_str =
cntl->http_request().uri().GetQuery(TIME_STR);
int64_t start_tm;
if (time_str == NULL) {
start_tm = butil::gettimeofday_us();
} else {
start_tm = ParseDateTime(*time_str);
if (start_tm < 0) {
os << "Invalid " << TIME_STR << "=`" << time_str << '\''
<< (use_html ? "</body></html>" : "");
os.move_to(cntl->response_attachment());
return;
}
}
int max_count = 100;
const std::string* max_scan_str =
cntl->http_request().uri().GetQuery(MAX_SCAN_STR);
if (max_scan_str) {
char* endptr;
int max_count2 = strtol(max_scan_str->c_str(), &endptr, 10);
if (*endptr == '\0') {
max_count = max_count2;
}
}
// Set up SpanFilter.
RpczSpanFilter filter;
const std::string* min_latency_str =
cntl->http_request().uri().GetQuery(MIN_LATENCY_STR);
if (min_latency_str) {
char* endptr;
filter.CheckLatency(strtoll(min_latency_str->c_str(), &endptr, 10));
}
const std::string* min_reqsize_str =
cntl->http_request().uri().GetQuery(MIN_REQUEST_SIZE_STR);
if (min_reqsize_str) {
char* endptr;
filter.CheckRequest(strtol(min_reqsize_str->c_str(), &endptr, 10));
}
const std::string* min_respsize_str =
cntl->http_request().uri().GetQuery(MIN_RESPONSE_SIZE_STR);
if (min_respsize_str) {
char* endptr;
filter.CheckResponse(strtol(min_respsize_str->c_str(), &endptr, 10));
}
uint64_t log_id = 0;
if (ParseUint64(cntl->http_request().uri().GetQuery(LOG_ID_STR),
&log_id)) {
filter.CheckLogId(log_id);
}
const std::string* error_code_str =
cntl->http_request().uri().GetQuery(ERROR_CODE_STR);
if (error_code_str) {
char* endptr;
filter.CheckErrorCode(strtol(error_code_str->c_str(), &endptr, 10));
}
max_count = std::max(std::min(max_count, 10000), 1);
std::deque<BriefSpan> spans;
ListSpans(start_tm, max_count, &spans, &filter);
if (spans.empty()) {
os << "Fail to find matched spans"
<< (use_html ? "</body></html>" : "");
os.move_to(cntl->response_attachment());
return;
}
if (use_html) {
const char* action = (FLAGS_enable_rpcz ? "disable" : "enable");
os << "<div><input type='button' onclick='location.href=\"/rpcz/"
<< action << "\";' value='" << action << "' /></div>" "<pre>\n";
}
for (size_t i = 0; i < spans.size(); ++i) {
BriefSpan& span = spans[i];
int64_t last_time = span.start_real_us();
PrintRealDateTime(os, last_time);
PrintElapse(os, span.latency_us() + last_time, &last_time);
os << ' ' << (span.type() == SPAN_TYPE_SERVER ? 'S' : 'C')
<< ' ' << TRACE_ID_STR << '=';
if (use_html) {
os << "<a href=\"/rpcz?" << TRACE_ID_STR
<< '=' << Hex(span.trace_id()) << "\">";
}
os << Hex(span.trace_id());
if (use_html) {
os << "</a>";
}
os << ' ' << SPAN_ID_STR << '=';
if (use_html) {
os << "<a href=\"/rpcz?" << TRACE_ID_STR << '='
<< Hex(span.trace_id())
<< '&' << SPAN_ID_STR << '=' << Hex(span.span_id()) << "\">";
}
os << Hex(span.span_id());
if (use_html) {
os << "</a>";
}
os << ' ' << LOG_ID_STR << '=';
if (FLAGS_rpcz_hex_log_id) {
os << Hex(span.log_id());
} else {
os << span.log_id();
}
os << ' ' << WebEscape(span.full_method_name()) << '(' << span.request_size()
<< ")=" << span.response_size();
if (span.error_code() == 0) {
os << " [OK]";
} else {
os << " [" << berror(span.error_code()) << "] ";
}
os << std::endl;
}
if (use_html) {
os << "</pre></body></html>";
}
os.move_to(cntl->response_attachment());
}
}