local _M = {} local old_tcp_connect local old_tcp_sslhandshake local old_udp_setpeername local timing local function before_connect(self, host, port, options) local destination if string.sub(host, 1, 5) == "unix:" then destination = host else destination = "tcp://" .. host .. ":" .. tostring(port) end self.__kong_timing_destination__ = destination timing.enter_context("connections") timing.enter_context(destination) timing.enter_context("connect") end local function after_connect() timing.leave_context() -- leave connect timing.leave_context() -- leave destination timing.leave_context() -- leave connections end local function before_sslhandshake(self, reused_session, server_name, _ssl_verify, _send_status_req) timing.enter_context("connections") timing.enter_context(self.__kong_timing_destination__ or "unknown") timing.enter_context("sslhandshake") timing.set_context_prop("attempt_reuse_session", reused_session ~= nil) timing.set_context_prop("sni", server_name) end local function after_sslhandshake() timing.leave_context() -- leave sslhandshake timing.leave_context() -- leave destination timing.leave_context() -- leave connections end local function before_setpeername(self, host, port) local destination if string.sub(host, 1, 5) == "unix:" then destination = host else destination = "udp://" .. host .. ":" .. port end self.__kong_timing_destination__ = destination timing.enter_context("connections") timing.enter_context(destination) timing.enter_context("setpeername") end local function after_setpeername() _M.leave_context() -- leave setpeername _M.leave_context() -- leave destination _M.leave_context() -- leave connections end local function patched_connect(self, ...) before_connect(self, ...) local ok, err = old_tcp_connect(self, ...) after_connect() return ok, err end local function patched_sslhandshake(self, ...) before_sslhandshake(self, ...) local ok, err = old_tcp_sslhandshake(self, ...) after_sslhandshake() return ok, err end local function after_tcp(sock) if not old_tcp_connect then old_tcp_connect = sock.connect end if not old_tcp_sslhandshake then old_tcp_sslhandshake = sock.sslhandshake end sock.connect = patched_connect sock.sslhandshake = patched_sslhandshake return sock end local function patched_setpeername(self, ...) before_setpeername(self, ...) local ok, err = old_udp_setpeername(self, ...) after_setpeername() return ok, err end local function after_udp(sock) if not old_udp_setpeername then old_udp_setpeername = sock.setpeername end sock.setpeername = patched_setpeername return sock end function _M.register_hooks(timing_module) local req_dyn_hook = require("kong.dynamic_hook") -- creating a new TCP socket object doesn't need any arguments req_dyn_hook.hook_function("timing", ngx.socket, "tcp", 0, { afters = { after_tcp }, }) -- creating a new UDP socket object doesn't need any arguments req_dyn_hook.hook_function("timing", ngx.socket, "udp", 0, { afters = { after_udp }, }) timing = timing_module end return _M