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: v15.2.5~119^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=2fe945f8a682e296b4354a1ee734e20106273759;p=ceph.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 (cherry picked from commit 5ea7bb8449a75f96ed6e4d4d1c1f3d31e27040f8) --- diff --git a/src/rgw/rgw_asio_frontend.cc b/src/rgw/rgw_asio_frontend.cc index 2b654f50192..5d097733624 100644 --- a/src/rgw/rgw_asio_frontend.cc +++ b/src/rgw/rgw_asio_frontend.cc @@ -95,6 +95,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 @@ -132,9 +160,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); @@ -177,8 +205,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()) {