From: Mark Kogan Date: Tue, 18 Feb 2020 10:59:35 +0000 (+0200) Subject: rgw: add access log to the beast frontend X-Git-Tag: wip-pdonnell-testing-20200918.022351~1051^2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=5ea7bb8449a75f96ed6e4d4d1c1f3d31e27040f8;p=ceph-ci.git rgw: add access log to the beast frontend Add to the Beast frontend an access log line similar to CivetWeb. attempting to adhere as much as possible to the Apache Combined Log Format. Fixes: https://tracker.ceph.com/issues/45920 rgw: use beast message for access log (cherry picked from commit 44ec38933cbe6cc864c56332cc99502d86568fdc) Co-authored-by: Casey Bodley Signed-off-by: Mark Kogan --- diff --git a/src/rgw/rgw_asio_frontend.cc b/src/rgw/rgw_asio_frontend.cc index deab1b0c66f..fbb2a064b2a 100644 --- a/src/rgw/rgw_asio_frontend.cc +++ b/src/rgw/rgw_asio_frontend.cc @@ -85,6 +85,34 @@ class StreamIO : public rgw::asio::ClientIO { } }; +// output the http version as a string, ie 'HTTP/1.1' +struct http_version { + unsigned major_ver; + unsigned minor_ver; + explicit http_version(unsigned version) + : major_ver(version / 10), minor_ver(version % 10) {} +}; +std::ostream& operator<<(std::ostream& out, const http_version& v) { + return out << "HTTP/" << v.major_ver << '.' << v.minor_ver; +} + +// log an http header value or '-' if it's missing +struct log_header { + const http::fields& fields; + http::field field; + std::string_view quote; + log_header(const http::fields& fields, http::field field, + std::string_view quote = "") + : fields(fields), field(field), quote(quote) {} +}; +std::ostream& operator<<(std::ostream& out, const log_header& h) { + auto p = h.fields.find(h.field); + if (p == h.fields.end()) { + return out << '-'; + } + return out << h.quote << p->value() << h.quote; +} + using SharedMutex = ceph::async::SharedMutex; template @@ -122,9 +150,9 @@ void handle_connection(boost::asio::io_context& context, ldout(cct, 20) << "failed to read header: " << ec.message() << dendl; return; } + auto& message = parser.get(); if (ec) { ldout(cct, 1) << "failed to read header: " << ec.message() << dendl; - auto& message = parser.get(); http::response response; response.result(http::status::bad_request); response.version(message.version() == 10 ? 10 : 11); @@ -167,8 +195,24 @@ void handle_connection(boost::asio::io_context& context, &real_client)))); RGWRestfulIO client(cct, &real_client_io); auto y = optional_yield{context, yield}; + int http_ret = 0; process_request(env.store, env.rest, &req, env.uri_prefix, - *env.auth_registry, &client, env.olog, y, scheduler); + *env.auth_registry, &client, env.olog, y, + scheduler, &http_ret); + + if (cct->_conf->subsys.should_gather(dout_subsys, 1)) { + // access log line elements begin per Apache Combined Log Format with additions following + const auto now = ceph::coarse_real_clock::now(); + using ceph::operator<<; // for coarse_real_time + ldout(cct, 1) << "beast: " << hex << &req << dec << ": " + << remote_endpoint.address() << " - - [" << now << "] \"" + << message.method_string() << ' ' << message.target() << ' ' + << http_version{message.version()} << "\" " << http_ret << ' ' + << client.get_bytes_sent() + client.get_bytes_received() << ' ' + << log_header{message, http::field::referer, "\""} << ' ' + << log_header{message, http::field::user_agent, "\""} << ' ' + << log_header{message, http::field::range} << dendl; + } } if (!parser.keep_alive()) {