Skip to content

Commit 84d4270

Browse files
authored
[EXPORTER] Log SSL Connection Information (#3113)
1 parent b0e8d7a commit 84d4270

File tree

9 files changed

+121
-6
lines changed

9 files changed

+121
-6
lines changed

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,9 @@ option(
215215
"Whether to include gzip compression for the OTLP http exporter in the SDK"
216216
OFF)
217217

218+
option(WITH_CURL_LOGGING "Whether to enable select CURL verbosity in OTel logs"
219+
OFF)
220+
218221
option(WITH_ZIPKIN "Whether to include the Zipkin exporter in the SDK" OFF)
219222

220223
option(WITH_PROMETHEUS "Whether to include the Prometheus Client in the SDK"

exporters/otlp/src/otlp_http_client.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,7 @@ OtlpHttpClient::createSession(
989989
request->SetBody(body_vec);
990990
request->ReplaceHeader("Content-Type", content_type);
991991
request->ReplaceHeader("User-Agent", options_.user_agent);
992+
request->EnableLogging(options_.console_debug);
992993

993994
if (options_.compression == "gzip")
994995
{

ext/include/opentelemetry/ext/http/client/curl/http_client_curl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ class Request : public opentelemetry::ext::http::client::Request
102102
compression_ = compression;
103103
}
104104

105+
void EnableLogging(bool is_log_enabled) noexcept override { is_log_enabled_ = is_log_enabled; }
106+
105107
public:
106108
opentelemetry::ext::http::client::Method method_;
107109
opentelemetry::ext::http::client::HttpSslOptions ssl_options_;
@@ -111,6 +113,7 @@ class Request : public opentelemetry::ext::http::client::Request
111113
std::chrono::milliseconds timeout_ms_{5000}; // ms
112114
opentelemetry::ext::http::client::Compression compression_{
113115
opentelemetry::ext::http::client::Compression::kNone};
116+
bool is_log_enabled_{false};
114117
};
115118

116119
class Response : public opentelemetry::ext::http::client::Response

ext/include/opentelemetry/ext/http/client/curl/http_operation_curl.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@ class HttpOperation
102102

103103
static size_t ReadMemoryCallback(char *buffer, size_t size, size_t nitems, void *userp);
104104

105+
static int CurlLoggerCallback(const CURL * /* handle */,
106+
curl_infotype type,
107+
const char *data,
108+
size_t size,
109+
void * /* clientp */) noexcept;
110+
105111
#if LIBCURL_VERSION_NUM >= 0x075000
106112
static int PreRequestCallback(void *clientp,
107113
char *conn_primary_ip,
@@ -152,7 +158,8 @@ class HttpOperation
152158
// Default connectivity and response size options
153159
bool is_raw_response = false,
154160
std::chrono::milliseconds http_conn_timeout = default_http_conn_timeout,
155-
bool reuse_connection = false);
161+
bool reuse_connection = false,
162+
bool is_log_enabled = false);
156163

157164
/**
158165
* Destroy CURL instance
@@ -300,6 +307,8 @@ class HttpOperation
300307

301308
const opentelemetry::ext::http::client::Compression &compression_;
302309

310+
const bool is_log_enabled_;
311+
303312
// Processed response headers and body
304313
long response_code_;
305314
std::vector<uint8_t> response_headers_;

ext/include/opentelemetry/ext/http/client/http_client.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ class Request
245245

246246
virtual void SetCompression(const Compression &compression) noexcept = 0;
247247

248+
virtual void EnableLogging(bool is_log_enabled) noexcept = 0;
249+
248250
virtual ~Request() = default;
249251
};
250252

ext/src/http/client/curl/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ else()
2424
PRIVATE ${CURL_LIBRARIES})
2525
endif()
2626

27+
if(WITH_CURL_LOGGING)
28+
target_compile_definitions(opentelemetry_http_client_curl
29+
PRIVATE ENABLE_CURL_LOGGING)
30+
endif()
31+
2732
if(WITH_OTLP_HTTP_COMPRESSION)
2833
if(TARGET ZLIB::ZLIB)
2934
target_link_libraries(

ext/src/http/client/curl/http_client_curl.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,10 @@ void Session::SendRequest(
116116
#endif
117117
}
118118

119-
curl_operation_.reset(new HttpOperation(http_request_->method_, url, http_request_->ssl_options_,
120-
callback_ptr, http_request_->headers_,
121-
http_request_->body_, http_request_->compression_, false,
122-
http_request_->timeout_ms_, reuse_connection));
119+
curl_operation_.reset(new HttpOperation(
120+
http_request_->method_, url, http_request_->ssl_options_, callback_ptr,
121+
http_request_->headers_, http_request_->body_, http_request_->compression_, false,
122+
http_request_->timeout_ms_, reuse_connection, http_request_->is_log_enabled_));
123123
bool success =
124124
CURLE_OK == curl_operation_->SendAsync(this, [this, callback](HttpOperation &operation) {
125125
if (operation.WasAborted())

ext/src/http/client/curl/http_operation_curl.cc

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "opentelemetry/ext/http/client/curl/http_client_curl.h"
2323
#include "opentelemetry/ext/http/client/curl/http_operation_curl.h"
2424
#include "opentelemetry/ext/http/client/http_client.h"
25+
#include "opentelemetry/nostd/string_view.h"
2526
#include "opentelemetry/sdk/common/global_log_handler.h"
2627
#include "opentelemetry/version.h"
2728

@@ -261,7 +262,8 @@ HttpOperation::HttpOperation(opentelemetry::ext::http::client::Method method,
261262
// Default connectivity and response size options
262263
bool is_raw_response,
263264
std::chrono::milliseconds http_conn_timeout,
264-
bool reuse_connection)
265+
bool reuse_connection,
266+
bool is_log_enabled)
265267
: is_aborted_(false),
266268
is_finished_(false),
267269
is_cleaned_(false),
@@ -281,6 +283,7 @@ HttpOperation::HttpOperation(opentelemetry::ext::http::client::Method method,
281283
request_nwrite_(0),
282284
session_state_(opentelemetry::ext::http::client::SessionState::Created),
283285
compression_(compression),
286+
is_log_enabled_(is_log_enabled),
284287
response_code_(0)
285288
{
286289
/* get a curl handle */
@@ -569,8 +572,77 @@ CURLcode HttpOperation::SetCurlOffOption(CURLoption option, curl_off_t value)
569572
return rc;
570573
}
571574

575+
int HttpOperation::CurlLoggerCallback(const CURL * /* handle */,
576+
curl_infotype type,
577+
const char *data,
578+
size_t size,
579+
void * /* clientp */) noexcept
580+
{
581+
nostd::string_view text_to_log{data, size};
582+
583+
if (!text_to_log.empty() && text_to_log[size - 1] == '\n')
584+
{
585+
text_to_log = text_to_log.substr(0, size - 1);
586+
}
587+
588+
if (type == CURLINFO_TEXT)
589+
{
590+
static const auto kTlsInfo = nostd::string_view("SSL connection using");
591+
static const auto kFailureMsg = nostd::string_view("Recv failure:");
592+
593+
if (text_to_log.substr(0, kTlsInfo.size()) == kTlsInfo)
594+
{
595+
OTEL_INTERNAL_LOG_INFO(text_to_log);
596+
}
597+
else if (text_to_log.substr(0, kFailureMsg.size()) == kFailureMsg)
598+
{
599+
OTEL_INTERNAL_LOG_ERROR(text_to_log);
600+
}
601+
// This guard serves as a catch-all block for all other less interesting output that should
602+
// remain available for maintainer internal use and for debugging purposes only.
603+
#ifdef OTEL_CURL_DEBUG
604+
else
605+
{
606+
OTEL_INTERNAL_LOG_DEBUG(text_to_log);
607+
}
608+
#endif // OTEL_CURL_DEBUG
609+
}
610+
// Same as above, this guard is meant only for internal use by maintainers, and should not be used
611+
// in production (information leak).
612+
#ifdef OTEL_CURL_DEBUG
613+
else if (type == CURLINFO_HEADER_OUT)
614+
{
615+
static const auto kHeaderSent = nostd::string_view("Send header => ");
616+
617+
while (!text_to_log.empty() && !std::iscntrl(text_to_log[0]))
618+
{
619+
const auto pos = text_to_log.find('\n');
620+
621+
if (pos != nostd::string_view::npos)
622+
{
623+
OTEL_INTERNAL_LOG_DEBUG(kHeaderSent << text_to_log.substr(0, pos - 1));
624+
text_to_log = text_to_log.substr(pos + 1);
625+
}
626+
}
627+
}
628+
else if (type == CURLINFO_HEADER_IN)
629+
{
630+
static const auto kHeaderRecv = nostd::string_view("Recv header => ");
631+
OTEL_INTERNAL_LOG_DEBUG(kHeaderRecv << text_to_log);
632+
}
633+
#endif // OTEL_CURL_DEBUG
634+
635+
return 0;
636+
}
637+
572638
CURLcode HttpOperation::Setup()
573639
{
640+
#ifdef ENABLE_CURL_LOGGING
641+
static constexpr auto kEnableCurlLogging = true;
642+
#else
643+
static constexpr auto kEnableCurlLogging = false;
644+
#endif // ENABLE_CURL_LOGGING
645+
574646
if (!curl_resource_.easy_handle)
575647
{
576648
return CURLE_FAILED_INIT;
@@ -581,11 +653,28 @@ CURLcode HttpOperation::Setup()
581653
curl_error_message_[0] = '\0';
582654
curl_easy_setopt(curl_resource_.easy_handle, CURLOPT_ERRORBUFFER, curl_error_message_);
583655

656+
// Support for custom debug function callback was added in version 7.9.6 so we guard against
657+
// exposing the default CURL output by keeping verbosity always disabled in lower versions.
658+
#if LIBCURL_VERSION_NUM < CURL_VERSION_BITS(7, 9, 6)
584659
rc = SetCurlLongOption(CURLOPT_VERBOSE, 0L);
585660
if (rc != CURLE_OK)
586661
{
587662
return rc;
588663
}
664+
#else
665+
rc = SetCurlLongOption(CURLOPT_VERBOSE, (is_log_enabled_ && kEnableCurlLogging) ? 1L : 0L);
666+
if (rc != CURLE_OK)
667+
{
668+
return rc;
669+
}
670+
671+
rc = SetCurlPtrOption(CURLOPT_DEBUGFUNCTION,
672+
reinterpret_cast<void *>(&HttpOperation::CurlLoggerCallback));
673+
if (rc != CURLE_OK)
674+
{
675+
return rc;
676+
}
677+
#endif
589678

590679
// Specify target URL
591680
rc = SetCurlStrOption(CURLOPT_URL, url_.c_str());

test_common/include/opentelemetry/test_common/ext/http/client/nosend/http_client_nosend.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ class Request : public opentelemetry::ext::http::client::Request
6969
compression_ = compression;
7070
}
7171

72+
void EnableLogging(bool is_log_enabled) noexcept override { is_log_enabled_ = is_log_enabled; }
73+
7274
public:
7375
opentelemetry::ext::http::client::Method method_;
7476
opentelemetry::ext::http::client::HttpSslOptions ssl_options_;
@@ -78,6 +80,7 @@ class Request : public opentelemetry::ext::http::client::Request
7880
std::chrono::milliseconds timeout_ms_{5000}; // ms
7981
opentelemetry::ext::http::client::Compression compression_{
8082
opentelemetry::ext::http::client::Compression::kNone};
83+
bool is_log_enabled_{false};
8184
};
8285

8386
class Response : public opentelemetry::ext::http::client::Response

0 commit comments

Comments
 (0)