module Labkit::NetHttpPublisher

Prepend to Ruby's Net/HTTP standard HTTP library to publish a notification whenever a HTTP request is triggered. Net::HTTP has different class methods for each http method. Those methods are delegated to corresponding instance methods. Eventually, `request` method is call to dispatch the HTTP request. Therefore, a prepender that override `request` method covers all HTTP calls.

For more information: github.com/ruby/ruby/blob/9b9cbbbc17bb5840581c7da37fd0feb0a7d4c1f3/lib/net/http.rb#L1510

Note: some use cases to take care of

Public Class Methods

labkit_prepend!() click to toggle source
# File lib/labkit/net_http_publisher.rb, line 29
def self.labkit_prepend!
  @prepend_mutex.synchronize do
    return if @prepended

    require "net/http"
    Net::HTTP.prepend(self)
    @prepended = true
  end
end

Public Instance Methods

request(request, *args, &block) click to toggle source
Calls superclass method
# File lib/labkit/net_http_publisher.rb, line 39
def request(request, *args, &block)
  return super unless started?

  start_time = ::Labkit::System.monotonic_time

  ActiveSupport::Notifications.instrument ::Labkit::EXTERNAL_HTTP_NOTIFICATION_TOPIC, create_request_payload(request) do |payload|
    response =
      begin
        super
      ensure
        payload[:duration] = (::Labkit::System.monotonic_time - start_time).to_f
      end
    payload[:code] = response.code
    response
  end
end

Private Instance Methods

create_request_payload(request) click to toggle source
# File lib/labkit/net_http_publisher.rb, line 58
def create_request_payload(request)
  payload = {
    method: request.method,
  }

  if request.uri.nil?
    path_uri = URI(request.path)
    payload[:host] = address
    payload[:path] = path_uri.path
    payload[:port] = port
    payload[:scheme] = use_ssl? ? "https" : "http"
    payload[:query] = path_uri.query
    payload[:fragment] = path_uri.fragment
  else
    payload[:host] = request.uri.host
    payload[:path] = request.uri.path
    payload[:port] = request.uri.port
    payload[:scheme] = request.uri.scheme
    payload[:query] = request.uri.query
    payload[:fragment] = request.uri.fragment
  end

  if proxy?
    payload[:proxy_host] = proxy_address
    payload[:proxy_port] = proxy_port
  end

  payload
end