1919#include < userver/clients/http/connect_to.hpp>
2020#include < userver/http/url.hpp>
2121#include < userver/server/request/task_inherited_data.hpp>
22+ #include < userver/utils/algo.hpp>
2223#include < userver/utils/assert.hpp>
2324#include < userver/utils/async.hpp>
2425#include < userver/utils/encoding/hex.hpp>
@@ -53,8 +54,6 @@ constexpr Status kLeastHttpCodeForDeadlineExpired{400};
5354
5455constexpr Status kFakeHttpErrorCode {599 };
5556
56- const std::string kTracingClientName = " external/" ;
57-
5857constexpr utils::TrivialBiMap kTestsuiteActions = [](auto selector) {
5958 return selector ()
6059 .Case (" timeout" , curl::errc::EasyErrorCode::kOperationTimedout )
@@ -100,6 +99,8 @@ bool IsSetCookie(std::string_view key) {
10099// Not a strict check, but OK for non-header line check
101100bool IsHttpStatusLineStart (const char * ptr, size_t size) { return (size > 5 && memcmp (ptr, " HTTP/" , 5 ) == 0 ); }
102101
102+ std::string ToString (HttpMethod method) { return std::string{ToStringView (method)}; }
103+
103104char * RfindNotSpace (char * ptr, size_t size) {
104105 for (char * p = ptr + size - 1 ; p >= ptr; --p) {
105106 const char c = *p;
@@ -484,7 +485,7 @@ void RequestState::OnCompleted(std::shared_ptr<RequestState> holder, std::error_
484485
485486 span.AddTag (tracing::kErrorFlag , true );
486487 span.AddTag (tracing::kErrorMessage , err.message ());
487- span.AddTag (tracing::kHttpStatusCode , kFakeHttpErrorCode );
488+ span.AddTag (tracing::kHttpResponseStatusCode , kFakeHttpErrorCode );
488489
489490 if (holder->errorbuffer_ .front ()) {
490491 LOG_DEBUG () << " cURL error details: " << holder->errorbuffer_ .data ();
@@ -506,7 +507,7 @@ void RequestState::OnCompleted(std::shared_ptr<RequestState> holder, std::error_
506507 }};
507508 std::visit (visitor, holder->data_ );
508509 } else {
509- span.AddTag (tracing::kHttpStatusCode , status_code);
510+ span.AddTag (tracing::kHttpResponseStatusCode , status_code);
510511 holder->response ()->SetStatusCode (status_code);
511512 holder->response ()->SetStats (easy.get_local_stats ());
512513
@@ -652,6 +653,39 @@ void RequestState::SetPluginsList(const std::vector<utils::NotNull<Plugin*>>& pl
652653
653654void RequestState::SetLoggedUrl (std::string url) { log_url_ = std::move (url); }
654655
656+ void RequestState::SetUrlTemplate (std::string url_template) { url_template_ = std::move (url_template); }
657+
658+ void RequestState::SetMethod (HttpMethod method) {
659+ switch (method) {
660+ case HttpMethod::kDelete :
661+ case HttpMethod::kOptions :
662+ easy ().set_custom_request (ToString (method));
663+ break ;
664+ case HttpMethod::kGet :
665+ easy ().set_http_get (true );
666+ easy ().set_custom_request (nullptr );
667+ break ;
668+ case HttpMethod::kHead :
669+ easy ().set_no_body (true );
670+ easy ().set_custom_request (nullptr );
671+ break ;
672+ // NOTE: set_post makes libcURL to read from stdin if no data is set
673+ case HttpMethod::kPost :
674+ case HttpMethod::kPut :
675+ case HttpMethod::kPatch :
676+ easy ().set_custom_request (ToString (method));
677+ // ensure a body as we should send Content-Length for this method
678+ if (!easy ().has_post_data ()) data ({});
679+ break ;
680+ };
681+ method_ = method;
682+ }
683+
684+ void RequestState::data (std::string data) {
685+ if (!data.empty ()) easy ().add_header (kHeaderExpect , " " , curl::easy::EmptyHeaderAction::kDoNotSend );
686+ easy ().set_post_fields (std::move (data));
687+ }
688+
655689const std::string& RequestState::GetLoggedOriginalUrl () const noexcept {
656690 // We may want to use original_url if effective_url is not available yet.
657691 return log_url_ ? *log_url_ : easy ().get_original_url ();
@@ -992,16 +1026,30 @@ void RequestState::ApplyTestsuiteConfig() {
9921026void RequestState::StartNewSpan (utils::impl::SourceLocation location) {
9931027 UINVARIANT (!span_storage_, " Attempt to reuse request while the previous one has not finished" );
9941028
995- span_storage_.emplace (
996- kTracingClientName + std::string{USERVER_NAMESPACE::http::ExtractHostname (easy ().get_original_url ())}, location
997- );
1029+ std::string span_name;
1030+ if (url_template_.has_value ()) {
1031+ span_name = utils::StrCat (ToStringView (method_), " " , url_template_.value ());
1032+ } else {
1033+ span_name = utils::StrCat (
1034+ ToStringView (method_), " " , USERVER_NAMESPACE::http::ExtractHostname (easy ().get_original_url ())
1035+ );
1036+ }
1037+ span_storage_.emplace (std::move (span_name), location);
1038+
9981039 auto & span = span_storage_->Get ();
9991040
10001041 auto request_editable_instance = GetEditableRequestInstance ();
10011042
10021043 tracing_manager_->FillRequestWithTracingContext (span, request_editable_instance);
10031044 plugin_pipeline_.HookCreateSpan (*this , span);
1004- span.AddTag (tracing::kHttpUrl , GetLoggedOriginalUrl ());
1045+ span.AddTag (tracing::kUrlFull , GetLoggedOriginalUrl ());
1046+ span.AddTag (
1047+ tracing::kServerAddress , std::string{USERVER_NAMESPACE::http::ExtractHostname (easy ().get_original_url ())}
1048+ );
1049+ span.AddTag (tracing::kHttpRequestMethod , std::string{ToStringView (method_)});
1050+ if (url_template_.has_value ()) {
1051+ span.AddTag (tracing::kHttpUrlTemplate , url_template_.value ());
1052+ }
10051053 span.AddTag (tracing::kMaxAttempts , retry_.retries );
10061054
10071055 // Span is local to a Request, it is not related to current coroutine
0 commit comments