]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: add operator<< for RGWEndpoint and simplify logging
authorOguzhan Ozmen <oozmen@bloomberg.net>
Sun, 8 Feb 2026 00:30:13 +0000 (00:30 +0000)
committerOguzhan Ozmen <oozmen@bloomberg.net>
Tue, 2 Jun 2026 22:16:20 +0000 (22:16 +0000)
Add ostream operator<< to RGWEndpoint struct for convenient logging of
endpoint details (url, original_url when different, and connect_to).
Update log statements across rgw_http_client.cc, rgw_rest_client.cc,
and rgw_rest_conn.cc to use the new operator for cleaner, more
consistent output.

Add unittest_rgw_http_client to test RGWEndpoint functionality.

Signed-off-by: Oguzhan Ozmen <oozmen@bloomberg.net>
src/rgw/rgw_http_client.cc
src/rgw/rgw_http_client.h
src/rgw/rgw_rest_client.cc
src/rgw/rgw_rest_conn.cc
src/test/rgw/CMakeLists.txt
src/test/rgw/test_rgw_http_client.cc [new file with mode: 0644]

index 94ed211c8c47184a4baeabb46be4deceb983abf2..1b1d5bae8b796ce194658c72a0dc5a742daca10e 100644 (file)
@@ -586,8 +586,7 @@ int RGWHTTPClient::init_request(rgw_http_req_data *_req_data)
 
   CURL *easy_handle = req_data->get_easy_handle();
 
-  dout(20) << "sending request to url=" << endpoint.get_url()
-    << " connect_to=" << endpoint.get_connect_to() << dendl;
+  dout(20) << "sending request to " << endpoint << dendl;
 
   curl_slist *h = headers_to_slist(headers);
 
@@ -605,9 +604,9 @@ int RGWHTTPClient::init_request(rgw_http_req_data *_req_data)
 
     req_data->connect_to_slist = curl_slist_append(req_data->connect_to_slist, endpoint.get_connect_to().c_str());
     if (! req_data->connect_to_slist) {
-      dout(0) << "ERROR: RGWHTTPClient::init_request failed to allocate connect_to_slist" << dendl;
+      dout(0) << "ERROR: RGWHTTPClient::init_request failed to allocate connect_to_slist: " << endpoint << dendl;
     } else {
-      dout(20) << "applying CURLOPT_CONNECT_TO=" << endpoint.get_connect_to() << " for url=" << endpoint.get_url() << dendl;
+      dout(20) << "applying CURLOPT_CONNECT_TO " << endpoint << dendl;
       curl_easy_setopt(easy_handle, CURLOPT_CONNECT_TO, req_data->connect_to_slist);
     }
   }
index 942824aa9d6ca91282eb42bfb2d092b53a790305..5aec7c406847b6509a95121820ce4640e6dcae7a 100644 (file)
@@ -75,6 +75,17 @@ public:
   void append_to_url(const std::string& suffix) {
     url.append(suffix);
   }
+
+  friend std::ostream& operator<<(std::ostream& os, const RGWEndpoint& ep) {
+    os << "RGWEndpoint: url=" << ep.url;
+    if (!ep.original_url.empty() && ep.original_url != ep.url) {
+      os << " original_url=" << ep.original_url;
+    }
+    if (!ep.connect_to.empty()) {
+      os << " connect_to=" << ep.connect_to;
+    }
+    return os;
+  }
 };
 
 class RGWHTTPClient : public RGWIOProvider,
index 9317587ac78167c62cd5c2555e2805f7cb926619..e82680e7b0ef91eac05c2b2634161f34105488b7 100644 (file)
@@ -702,7 +702,8 @@ void RGWRESTStreamS3PutObj::send_init(const rgw_obj& obj)
   //do not encode slash in object key name
   url_encode(resource_str, resource, false);
 
-  ldpp_dout(this, 20) << __func__ << "(): host = " << host << " , resource = " << resource << " , new_host = " << new_host << " , new_url = " << new_endpoint.get_url()  << dendl;
+  ldpp_dout(this, 20) << __func__ << "(): host = " << host << " , resource = " << resource
+    << " , new_host = " << new_host << " , new_endpoint = " << new_endpoint  << dendl;
 
   method = "PUT";
   headers_gen.init(method, new_host, resource_prefix, new_endpoint, resource, params, api_name);
@@ -858,7 +859,9 @@ int RGWRESTStreamRWRequest::do_send_prepare(const DoutPrefixProvider *dpp, RGWAc
 
   headers_gen.emplace(cct, &new_env, &new_info);
 
-  ldpp_dout(this, 20) << __func__ << "(): host = " << host << " , resource = " << resource << " , new_host = " << new_host << " , new_url = " << new_endpoint.get_url()  << " , new_resource = " << new_resource << dendl;
+  ldpp_dout(this, 20) << __func__ << "(): host = " << host << " , resource = " << resource
+    << " , new_host = " << new_host << " , new_endpoint = " << new_endpoint
+    << " , new_resource = " << new_resource << dendl;
 
   headers_gen->init(method, new_host, resource_prefix, new_endpoint, new_resource, params, api_name);
 
index 6c86d4e29fd97650c66c0d1d103f3458318867d0..cdc8a2f6cea940428459e6da7ccac92012386ada 100644 (file)
@@ -204,7 +204,7 @@ int RGWRESTConn::get_endpoint(RGWEndpoint& endpoint)
     static constexpr uint32_t CONN_STATUS_EXPIRE_SECS = 2;
     if (diff >= CONN_STATUS_EXPIRE_SECS) {
       resolved_endpoints[ep_url].status.store(ceph::real_clock::zero());
-      ldout(cct, 10) << "endpoint " << endpoint.get_url() << " unconnectable status expired. mark it connectable" << dendl;
+      ldout(cct, 10) << endpoint << " unconnectable status expired. mark it connectable" << dendl;
       break;
     }
     num++;
@@ -216,8 +216,7 @@ int RGWRESTConn::get_endpoint(RGWEndpoint& endpoint)
   }
 
   get_connect_to_mapping_for_url(endpoint);
-  ldout(cct, 20) << "get_endpoint picked endpoint url=" << endpoint.get_url()
-    << " connect_to=" << endpoint.get_connect_to() << dendl;
+  ldout(cct, 20) << "get_endpoint picked " << endpoint << dendl;
 
   return 0;
 }
@@ -234,8 +233,8 @@ void RGWRESTConn::set_endpoint_unconnectable(const RGWEndpoint& endpoint)
   const string& orig_url = endpoint.get_original_url();
 
   if (orig_url.empty() || resolved_endpoints.find(orig_url) == resolved_endpoints.end()) {
-    ldout(cct, 0) << "ERROR: endpoint is not a valid or doesn't have status. "
-                  << " original_url=" << orig_url << " current_url=" << endpoint.get_url() << dendl;
+    ldout(cct, 0) << "ERROR: endpoint is not a valid or doesn't have status: "
+                  << endpoint << dendl;
     return;
   }
 
index c587b5834dcbc539b3cc81bca7045a8e76978a8d..b3ebfb1a309562ed77b58df43d29664bccf406a5 100644 (file)
@@ -469,3 +469,9 @@ target_link_libraries(unittest_rgw_async_utils ${rgw_libs} ${UNITTEST_LIBS})
 add_executable(unittest_rgw_tag test_rgw_tag.cc)
 add_ceph_unittest(unittest_rgw_tag)
 target_link_libraries(unittest_rgw_tag ${rgw_libs} ${UNITTEST_LIBS})
+
+# unittest_rgw_http_client
+add_executable(unittest_rgw_http_client test_rgw_http_client.cc)
+add_ceph_unittest(unittest_rgw_http_client)
+target_link_libraries(unittest_rgw_http_client
+  rgw_common ${rgw_libs} ${UNITTEST_LIBS})
diff --git a/src/test/rgw/test_rgw_http_client.cc b/src/test/rgw/test_rgw_http_client.cc
new file mode 100644 (file)
index 0000000..79f80c6
--- /dev/null
@@ -0,0 +1,132 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:nil -*-
+// vim: ts=8 sw=2 sts=2 expandtab ft=cpp
+
+#include <gtest/gtest.h>
+#include <sstream>
+
+#include "rgw_http_client.h"
+
+using namespace std;
+
+// Tests for RGWEndpoint
+
+TEST(RGWEndpointTest, default_constructor) {
+  RGWEndpoint ep;
+  EXPECT_TRUE(ep.get_url().empty());
+  EXPECT_TRUE(ep.get_original_url().empty());
+  EXPECT_TRUE(ep.get_connect_to().empty());
+}
+
+TEST(RGWEndpointTest, constructor_sets_url_and_original_url) {
+  RGWEndpoint ep("http://example.com:8080");
+  EXPECT_EQ(ep.get_url(), "http://example.com:8080");
+  EXPECT_EQ(ep.get_original_url(), "http://example.com:8080");
+}
+
+TEST(RGWEndpointTest, constructor_with_connect_to) {
+  RGWEndpoint ep("http://example.com:8080", "example.com:8080:192.168.1.1:8080");
+  EXPECT_EQ(ep.get_url(), "http://example.com:8080");
+  EXPECT_EQ(ep.get_original_url(), "http://example.com:8080");
+  EXPECT_EQ(ep.get_connect_to(), "example.com:8080:192.168.1.1:8080");
+}
+
+TEST(RGWEndpointTest, set_url_on_default_constructed_sets_original) {
+  RGWEndpoint ep;
+  EXPECT_TRUE(ep.get_original_url().empty());
+
+  ep.set_url("http://first.example.com");
+  EXPECT_EQ(ep.get_url(), "http://first.example.com");
+  EXPECT_EQ(ep.get_original_url(), "http://first.example.com");
+
+  // Second set_url should NOT change original_url
+  ep.set_url("http://second.example.com");
+  EXPECT_EQ(ep.get_url(), "http://second.example.com");
+  EXPECT_EQ(ep.get_original_url(), "http://first.example.com");
+}
+
+TEST(RGWEndpointTest, set_url_does_not_change_original_after_constructor) {
+  RGWEndpoint ep("http://original.example.com");
+
+  ep.set_url("http://modified.example.com");
+  EXPECT_EQ(ep.get_url(), "http://modified.example.com");
+  EXPECT_EQ(ep.get_original_url(), "http://original.example.com");
+}
+
+TEST(RGWEndpointTest, with_url_returns_copy_with_new_url) {
+  RGWEndpoint ep("http://original.example.com");
+  ep.set_connect_to("original.example.com:80:192.168.1.1:80");
+
+  RGWEndpoint ep2 = ep.with_url("http://modified.example.com");
+
+  // Original unchanged
+  EXPECT_EQ(ep.get_url(), "http://original.example.com");
+  EXPECT_EQ(ep.get_original_url(), "http://original.example.com");
+
+  // Copy has new url but preserves original_url and connect_to
+  EXPECT_EQ(ep2.get_url(), "http://modified.example.com");
+  EXPECT_EQ(ep2.get_original_url(), "http://original.example.com");
+  EXPECT_EQ(ep2.get_connect_to(), "original.example.com:80:192.168.1.1:80");
+}
+
+TEST(RGWEndpointTest, set_connect_to) {
+  RGWEndpoint ep("http://example.com:8080");
+  EXPECT_TRUE(ep.get_connect_to().empty());
+
+  ep.set_connect_to("example.com:8080:192.168.1.1:8080");
+  EXPECT_EQ(ep.get_connect_to(), "example.com:8080:192.168.1.1:8080");
+}
+
+TEST(RGWEndpointTest, add_trailing_slash) {
+  RGWEndpoint ep("http://example.com:8080");
+  ep.add_trailing_slash();
+  EXPECT_EQ(ep.get_url(), "http://example.com:8080/");
+
+  // Should not add another slash
+  ep.add_trailing_slash();
+  EXPECT_EQ(ep.get_url(), "http://example.com:8080/");
+}
+
+TEST(RGWEndpointTest, append_to_url) {
+  RGWEndpoint ep("http://example.com:8080");
+  ep.append_to_url("/path/to/resource");
+  EXPECT_EQ(ep.get_url(), "http://example.com:8080/path/to/resource");
+}
+
+// Tests for operator<<
+
+TEST(RGWEndpointTest, ostream_operator_url_only) {
+  RGWEndpoint ep("http://example.com:8080");
+  std::ostringstream oss;
+  oss << ep;
+  EXPECT_EQ(oss.str(), "RGWEndpoint: url=http://example.com:8080");
+}
+
+TEST(RGWEndpointTest, ostream_operator_with_different_original_url) {
+  RGWEndpoint ep;
+  ep.set_url("http://original.example.com:8080");
+  ep.set_url("http://modified.example.com:8080");  // original_url stays the same
+
+  std::ostringstream oss;
+  oss << ep;
+  EXPECT_EQ(oss.str(), "RGWEndpoint: url=http://modified.example.com:8080 original_url=http://original.example.com:8080");
+}
+
+TEST(RGWEndpointTest, ostream_operator_with_connect_to) {
+  RGWEndpoint ep("http://example.com:8080");
+  ep.set_connect_to("example.com:8080:192.168.1.1:8080");
+
+  std::ostringstream oss;
+  oss << ep;
+  EXPECT_EQ(oss.str(), "RGWEndpoint: url=http://example.com:8080 connect_to=example.com:8080:192.168.1.1:8080");
+}
+
+TEST(RGWEndpointTest, ostream_operator_full) {
+  RGWEndpoint ep;
+  ep.set_url("http://original.example.com:8080");
+  ep.set_url("http://192.168.1.1:8080");
+  ep.set_connect_to("original.example.com:8080:192.168.1.1:8080");
+
+  std::ostringstream oss;
+  oss << ep;
+  EXPECT_EQ(oss.str(), "RGWEndpoint: url=http://192.168.1.1:8080 original_url=http://original.example.com:8080 connect_to=original.example.com:8080:192.168.1.1:8080");
+}