55#else
66#include < netdb.h> // addrinfo, gai_strerror, getaddrinfo, freeaddrinfo
77#include < netinet/in.h> // htons, IPPROTO_TCP
8- #include < sys/poll.h> // pollfd, POLLHUP
8+ #include < sys/poll.h> // pollfd
99#include < sys/socket.h> // AF_INET, connect, recv, send, sockaddr, sockaddr_in, socket, SOCK_STREAM
1010#include < unistd.h> // close, ssize_t
1111
1818#include < thread>
1919
2020#include " databento/exceptions.hpp" // TcpError
21+ #include " databento/log.hpp" // ILogReceiver
2122
2223using databento::detail::TcpClient;
2324using Status = databento::IReadable::Status;
@@ -32,12 +33,13 @@ int GetErrNo() {
3233}
3334} // namespace
3435
35- TcpClient::TcpClient (const std::string& gateway, std::uint16_t port)
36- : TcpClient{gateway, port, {}} {}
36+ TcpClient::TcpClient (ILogReceiver* log_receiver, const std::string& gateway,
37+ std::uint16_t port)
38+ : TcpClient{log_receiver, gateway, port, {}} {}
3739
38- TcpClient::TcpClient (const std::string& gateway, std:: uint16_t port ,
39- RetryConf retry_conf)
40- : socket_{InitSocket (gateway, port, retry_conf)} {}
40+ TcpClient::TcpClient (ILogReceiver* log_receiver, const std::string& gateway,
41+ std:: uint16_t port, RetryConf retry_conf)
42+ : socket_{InitSocket (log_receiver, gateway, port, retry_conf)} {}
4143
4244void TcpClient::WriteAll (std::string_view str) {
4345 WriteAll (reinterpret_cast <const std::byte*>(str.data ()), str.length ());
@@ -103,9 +105,12 @@ databento::IReadable::Result TcpClient::ReadSome(std::byte* buffer,
103105
104106void TcpClient::Close () { socket_.Close (); }
105107
106- databento::detail::ScopedFd TcpClient::InitSocket (const std::string& gateway,
108+ databento::detail::ScopedFd TcpClient::InitSocket (ILogReceiver* log_receiver,
109+ const std::string& gateway,
107110 std::uint16_t port,
108111 RetryConf retry_conf) {
112+ static constexpr auto kMethod = " TcpClient::TcpClient" ;
113+
109114 const detail::Socket fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
110115 if (fd == -1 ) {
111116 throw TcpError{::GetErrNo (), " Failed to create socket" };
@@ -121,7 +126,7 @@ databento::detail::ScopedFd TcpClient::InitSocket(const std::string& gateway,
121126 const auto ret =
122127 ::getaddrinfo (gateway.c_str(), std::to_string(port).c_str(), &hints, &out);
123128 if (ret != 0 ) {
124- throw InvalidArgumentError{" TcpClient::TcpClient " , " addr" , ::gai_strerror (ret)};
129+ throw InvalidArgumentError{kMethod , " addr" , ::gai_strerror (ret)};
125130 }
126131 std::unique_ptr<addrinfo, decltype (&::freeaddrinfo)> res{out, &::freeaddrinfo};
127132 const auto max_attempts = std::max<std::uint32_t >(retry_conf.max_attempts , 1 );
@@ -134,7 +139,12 @@ databento::detail::ScopedFd TcpClient::InitSocket(const std::string& gateway,
134139 err_msg << " Socket failed to connect after " << max_attempts << " attempts" ;
135140 throw TcpError{::GetErrNo (), err_msg.str ()};
136141 }
137- // TODO(cg): Log
142+ std::ostringstream log_msg;
143+ log_msg << ' [' << kMethod << " ] Connection attempt " << (attempt + 1 ) << " to "
144+ << gateway << ' :' << port << " failed, retrying in " << backoff.count ()
145+ << " seconds" ;
146+ log_receiver->Receive (LogLevel::Warning, log_msg.str ());
147+
138148 std::this_thread::sleep_for (backoff);
139149 backoff = (std::min)(backoff * 2 , retry_conf.max_wait );
140150 }
0 commit comments