diff --git a/gennghttpxfun.py b/gennghttpxfun.py index f6d0e11c..ca40cabb 100755 --- a/gennghttpxfun.py +++ b/gennghttpxfun.py @@ -152,6 +152,8 @@ LOGVARS = [ "ssl_protocol", "ssl_session_id", "ssl_session_reused", + "backend_host", + "backend_port", ] if __name__ == '__main__': diff --git a/src/shrpx.cc b/src/shrpx.cc index 98985c64..ece98e36 100644 --- a/src/shrpx.cc +++ b/src/shrpx.cc @@ -2082,6 +2082,10 @@ Logging: * $ssl_session_id: session ID for SSL/TLS connection. * $ssl_session_reused: "r" if SSL/TLS session was reused. Otherwise, "." + * $backend_host: backend host used to fulfill the + request. "-" if backend host is not available. + * $backend_port: backend port used to fulfill the + request. "-" if backend host is not available. The variable can be enclosed by "{" and "}" for disambiguation (e.g., ${remote_addr}). diff --git a/src/shrpx_api_downstream_connection.cc b/src/shrpx_api_downstream_connection.cc index 1997a6f6..2b618d64 100644 --- a/src/shrpx_api_downstream_connection.cc +++ b/src/shrpx_api_downstream_connection.cc @@ -301,9 +301,10 @@ void APIDownstreamConnection::on_upstream_change(Upstream *uptream) {} bool APIDownstreamConnection::poolable() const { return false; } -DownstreamAddrGroup * +const std::shared_ptr & APIDownstreamConnection::get_downstream_addr_group() const { - return nullptr; + static std::shared_ptr s; + return s; } DownstreamAddr *APIDownstreamConnection::get_addr() const { return nullptr; } diff --git a/src/shrpx_api_downstream_connection.h b/src/shrpx_api_downstream_connection.h index f80341c7..5c1dd4eb 100644 --- a/src/shrpx_api_downstream_connection.h +++ b/src/shrpx_api_downstream_connection.h @@ -54,7 +54,8 @@ public: // true if this object is poolable. virtual bool poolable() const; - virtual DownstreamAddrGroup *get_downstream_addr_group() const; + virtual const std::shared_ptr & + get_downstream_addr_group() const; virtual DownstreamAddr *get_addr() const; int send_reply(unsigned int http_status, int api_status); diff --git a/src/shrpx_client_handler.cc b/src/shrpx_client_handler.cc index 2c9b2a10..bd609381 100644 --- a/src/shrpx_client_handler.cc +++ b/src/shrpx_client_handler.cc @@ -643,7 +643,7 @@ void ClientHandler::pool_downstream_connection( dconn->set_client_handler(nullptr); - auto group = dconn->get_downstream_addr_group(); + auto &group = dconn->get_downstream_addr_group(); if (LOG_ENABLED(INFO)) { CLOG(INFO, this) << "Pooling downstream connection DCONN:" << dconn.get() @@ -1143,7 +1143,8 @@ void ClientHandler::write_accesslog(Downstream *downstream) { upstream_accesslog( get_config()->logging.access.format, LogSpec{ - downstream, StringRef{ipaddr_}, http2::to_method_string(req.method), + downstream, downstream->get_addr(), StringRef{ipaddr_}, + http2::to_method_string(req.method), req.method == HTTP_CONNECT ? StringRef(req.authority) @@ -1176,7 +1177,7 @@ void ClientHandler::write_accesslog(int major, int minor, unsigned int status, upstream_accesslog(get_config()->logging.access.format, LogSpec{ - nullptr, StringRef(ipaddr_), + nullptr, nullptr, StringRef(ipaddr_), StringRef::from_lit("-"), // method StringRef::from_lit("-"), // path, StringRef(alpn_), nghttp2::ssl::get_tls_session_info( diff --git a/src/shrpx_config.cc b/src/shrpx_config.cc index 121ebbab..2eb208a3 100644 --- a/src/shrpx_config.cc +++ b/src/shrpx_config.cc @@ -434,6 +434,14 @@ LogFragmentType log_var_lookup_token(const char *name, size_t namelen) { return SHRPX_LOGF_SSL_PROTOCOL; } break; + case 't': + if (util::strieq_l("backend_hos", name, 11)) { + return SHRPX_LOGF_BACKEND_HOST; + } + if (util::strieq_l("backend_por", name, 11)) { + return SHRPX_LOGF_BACKEND_PORT; + } + break; } break; case 14: diff --git a/src/shrpx_downstream.cc b/src/shrpx_downstream.cc index 8b57a33f..b30cab74 100644 --- a/src/shrpx_downstream.cc +++ b/src/shrpx_downstream.cc @@ -124,6 +124,7 @@ Downstream::Downstream(Upstream *upstream, MemchunkPool *mcpool, response_buf_(mcpool), upstream_(upstream), blocked_link_(nullptr), + addr_(nullptr), num_retry_(0), stream_id_(stream_id), assoc_stream_id_(-1), @@ -943,4 +944,13 @@ void Downstream::add_rcbuf(nghttp2_rcbuf *rcbuf) { rcbufs_.push_back(rcbuf); } +void Downstream::set_downstream_addr_group( + const std::shared_ptr &group) { + group_ = group; +} + +void Downstream::set_addr(const DownstreamAddr *addr) { addr_ = addr; } + +const DownstreamAddr *Downstream::get_addr() const { return addr_; } + } // namespace shrpx diff --git a/src/shrpx_downstream.h b/src/shrpx_downstream.h index 9f5c7f67..8ae62847 100644 --- a/src/shrpx_downstream.h +++ b/src/shrpx_downstream.h @@ -49,6 +49,8 @@ namespace shrpx { class Upstream; class DownstreamConnection; struct BlockedLink; +struct DownstreamAddrGroup; +struct DownstreamAddr; class FieldStore { public: @@ -382,6 +384,12 @@ public: void add_rcbuf(nghttp2_rcbuf *rcbuf); + void + set_downstream_addr_group(const std::shared_ptr &group); + void set_addr(const DownstreamAddr *addr); + + const DownstreamAddr *get_addr() const; + enum { EVENT_ERROR = 0x1, EVENT_TIMEOUT = 0x2, @@ -429,6 +437,10 @@ private: // only used by HTTP/2 or SPDY upstream BlockedLink *blocked_link_; + // The backend address used to fulfill this request. These are for + // logging purpose. + std::shared_ptr group_; + const DownstreamAddr *addr_; // How many times we tried in backend connection size_t num_retry_; // The stream ID in frontend connection diff --git a/src/shrpx_downstream_connection.h b/src/shrpx_downstream_connection.h index 0372496d..03c4afe8 100644 --- a/src/shrpx_downstream_connection.h +++ b/src/shrpx_downstream_connection.h @@ -61,7 +61,8 @@ public: // true if this object is poolable. virtual bool poolable() const = 0; - virtual DownstreamAddrGroup *get_downstream_addr_group() const = 0; + virtual const std::shared_ptr & + get_downstream_addr_group() const = 0; virtual DownstreamAddr *get_addr() const = 0; void set_client_handler(ClientHandler *client_handler); diff --git a/src/shrpx_health_monitor_downstream_connection.cc b/src/shrpx_health_monitor_downstream_connection.cc index ddaf6db5..01bdfb9a 100644 --- a/src/shrpx_health_monitor_downstream_connection.cc +++ b/src/shrpx_health_monitor_downstream_connection.cc @@ -95,9 +95,10 @@ void HealthMonitorDownstreamConnection::on_upstream_change(Upstream *uptream) {} bool HealthMonitorDownstreamConnection::poolable() const { return false; } -DownstreamAddrGroup * +const std::shared_ptr & HealthMonitorDownstreamConnection::get_downstream_addr_group() const { - return nullptr; + static std::shared_ptr s; + return s; } DownstreamAddr *HealthMonitorDownstreamConnection::get_addr() const { diff --git a/src/shrpx_health_monitor_downstream_connection.h b/src/shrpx_health_monitor_downstream_connection.h index ddf30878..7439e83b 100644 --- a/src/shrpx_health_monitor_downstream_connection.h +++ b/src/shrpx_health_monitor_downstream_connection.h @@ -54,7 +54,8 @@ public: // true if this object is poolable. virtual bool poolable() const; - virtual DownstreamAddrGroup *get_downstream_addr_group() const; + virtual const std::shared_ptr & + get_downstream_addr_group() const; virtual DownstreamAddr *get_addr() const; }; diff --git a/src/shrpx_http2_downstream_connection.cc b/src/shrpx_http2_downstream_connection.cc index c6213a11..fb601f43 100644 --- a/src/shrpx_http2_downstream_connection.cc +++ b/src/shrpx_http2_downstream_connection.cc @@ -538,7 +538,7 @@ int Http2DownstreamConnection::on_timeout() { return submit_rst_stream(downstream_, NGHTTP2_NO_ERROR); } -DownstreamAddrGroup * +const std::shared_ptr & Http2DownstreamConnection::get_downstream_addr_group() const { return http2session_->get_downstream_addr_group(); } diff --git a/src/shrpx_http2_downstream_connection.h b/src/shrpx_http2_downstream_connection.h index f8195560..cdc55b9f 100644 --- a/src/shrpx_http2_downstream_connection.h +++ b/src/shrpx_http2_downstream_connection.h @@ -64,7 +64,8 @@ public: // migrate to another Http2Session object. virtual bool poolable() const { return false; } - virtual DownstreamAddrGroup *get_downstream_addr_group() const; + virtual const std::shared_ptr & + get_downstream_addr_group() const; virtual DownstreamAddr *get_addr() const; int send(); diff --git a/src/shrpx_http2_session.cc b/src/shrpx_http2_session.cc index 330287bd..445e7817 100644 --- a/src/shrpx_http2_session.cc +++ b/src/shrpx_http2_session.cc @@ -976,6 +976,10 @@ int on_response_headers(Http2Session *http2session, Downstream *downstream, resp.http_major = 2; resp.http_minor = 0; + downstream->set_downstream_addr_group( + http2session->get_downstream_addr_group()); + downstream->set_addr(http2session->get_addr()); + if (LOG_ENABLED(INFO)) { std::stringstream ss; for (auto &nv : nva) { @@ -2126,8 +2130,9 @@ bool Http2Session::max_concurrency_reached(size_t extra) const { session_, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS); } -DownstreamAddrGroup *Http2Session::get_downstream_addr_group() const { - return group_.get(); +const std::shared_ptr & +Http2Session::get_downstream_addr_group() const { + return group_; } void Http2Session::add_to_avail_freelist() { diff --git a/src/shrpx_http2_session.h b/src/shrpx_http2_session.h index a2f46ce7..64bb9b05 100644 --- a/src/shrpx_http2_session.h +++ b/src/shrpx_http2_session.h @@ -162,7 +162,7 @@ public: DownstreamAddr *get_addr() const; - DownstreamAddrGroup *get_downstream_addr_group() const; + const std::shared_ptr &get_downstream_addr_group() const; int handle_downstream_push_promise(Downstream *downstream, int32_t promised_stream_id); diff --git a/src/shrpx_http_downstream_connection.cc b/src/shrpx_http_downstream_connection.cc index 077844c4..deb3c7e0 100644 --- a/src/shrpx_http_downstream_connection.cc +++ b/src/shrpx_http_downstream_connection.cc @@ -565,7 +565,7 @@ int HttpDownstreamConnection::end_upload_data() { namespace { void remove_from_pool(HttpDownstreamConnection *dconn) { - auto group = dconn->get_downstream_addr_group(); + auto &group = dconn->get_downstream_addr_group(); auto &shared_addr = group->shared_addr; if (shared_addr->affinity == AFFINITY_NONE) { @@ -677,6 +677,11 @@ int htp_hdrs_completecb(http_parser *htp) { resp.http_minor = 1; } + auto dconn = downstream->get_downstream_connection(); + + downstream->set_downstream_addr_group(dconn->get_downstream_addr_group()); + downstream->set_addr(dconn->get_addr()); + if (resp.fs.parse_content_length() != 0) { downstream->set_response_state(Downstream::MSG_BAD_HEADER); return -1; @@ -1192,9 +1197,9 @@ int HttpDownstreamConnection::actual_signal_write() { int HttpDownstreamConnection::noop() { return 0; } -DownstreamAddrGroup * +const std::shared_ptr & HttpDownstreamConnection::get_downstream_addr_group() const { - return group_.get(); + return group_; } DownstreamAddr *HttpDownstreamConnection::get_addr() const { return addr_; } diff --git a/src/shrpx_http_downstream_connection.h b/src/shrpx_http_downstream_connection.h index 98a58d52..03050d8a 100644 --- a/src/shrpx_http_downstream_connection.h +++ b/src/shrpx_http_downstream_connection.h @@ -64,7 +64,8 @@ public: virtual bool poolable() const; - virtual DownstreamAddrGroup *get_downstream_addr_group() const; + virtual const std::shared_ptr & + get_downstream_addr_group() const; virtual DownstreamAddr *get_addr() const; int read_clear(); diff --git a/src/shrpx_log.cc b/src/shrpx_log.cc index de42adae..935dee37 100644 --- a/src/shrpx_log.cc +++ b/src/shrpx_log.cc @@ -45,6 +45,7 @@ #include "shrpx_config.h" #include "shrpx_downstream.h" +#include "shrpx_worker.h" #include "util.h" #include "template.h" @@ -367,6 +368,21 @@ void upstream_accesslog(const std::vector &lfv, std::tie(p, avail) = copy_l(lgsp.tls_info->session_reused ? "r" : ".", avail, p); break; + case SHRPX_LOGF_BACKEND_HOST: + if (!lgsp.downstream_addr) { + std::tie(p, avail) = copy_l("-", avail, p); + break; + } + std::tie(p, avail) = copy(lgsp.downstream_addr->host, avail, p); + break; + case SHRPX_LOGF_BACKEND_PORT: + if (!lgsp.downstream_addr) { + std::tie(p, avail) = copy_l("-", avail, p); + break; + } + std::tie(p, avail) = + copy(util::utos(lgsp.downstream_addr->port), avail, p); + break; case SHRPX_LOGF_NONE: break; default: diff --git a/src/shrpx_log.h b/src/shrpx_log.h index 24867b0b..1b766450 100644 --- a/src/shrpx_log.h +++ b/src/shrpx_log.h @@ -85,6 +85,7 @@ using namespace nghttp2; namespace shrpx { class Downstream; +struct DownstreamAddr; enum SeverityLevel { INFO, NOTICE, WARN, ERROR, FATAL }; @@ -131,6 +132,8 @@ enum LogFragmentType { SHRPX_LOGF_SSL_PROTOCOL, SHRPX_LOGF_SSL_SESSION_ID, SHRPX_LOGF_SSL_SESSION_REUSED, + SHRPX_LOGF_BACKEND_HOST, + SHRPX_LOGF_BACKEND_PORT, }; struct LogFragment { @@ -142,6 +145,7 @@ struct LogFragment { struct LogSpec { Downstream *downstream; + const DownstreamAddr *downstream_addr; StringRef remote_addr; StringRef method; StringRef path;