void RpczService::default_method()

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());
    }
}