Skip to content

Rails Integration for more insightful Net:HTTP Request Profiling

Thomas Witt edited this page Aug 13, 2025 · 1 revision

Inspired by the riak integration, I wanted to have more insightful outputs about NET HTTP Requests to common services. It works together with my DynamoDB Integration and my OpenSearch Integration so that requests do not show double.

# config/initializers/net_http_profiler.rb

# Enhanced Net::HTTP profiling that skips DynamoDB and OpenSearch requests
# to avoid duplicate profiling, but shows all other HTTP requests with details

begin
  require 'rack-mini-profiler'
rescue LoadError
  # Rack::MiniProfiler not present; no-op.
end

require 'net/http'

if defined?(::Rack::MiniProfiler) && defined?(::Net::HTTP)
  Rails.application.config.after_initialize do
    # First unprofile the default Net::HTTP profiling to replace it with our own
    if defined?(Net::HTTP)
      Rack::MiniProfiler.unprofile_method(Net::HTTP, :request) rescue nil
    end

    # Now add our custom profiling
    module NetHttpSelectiveProfiler
      def request(request, *args, &block)
        # Check if MiniProfiler is active
        if ::Rack::MiniProfiler.current&.measure
          # Check if we're already inside a service-specific profiler
          timer = ::Rack::MiniProfiler.current&.current_timer
          timer_name = timer&.name || ''

          # Skip if we're inside DynamoDB or OpenSearch profiler
          if timer_name.start_with?('SQL: ') || timer_name.start_with?('OpenSearch:')
            # We're inside a service-specific profiler, don't double-profile
            super
          else
            # Profile this HTTP request with detailed information
            host = @address || 'unknown'
            port = @port || 'unknown'
            method = request.method || 'unknown'
            path = request.path || '/'

            # Identify the service for better labeling
            service = identify_service(host, port, path)

            if service == :dynamodb || service == :opensearch
              # Skip profiling for these as they have their own profilers
              super
            else
              # Build a descriptive label
              label = if service.is_a?(String)
                  "#{service}: #{method} #{path}"
              else
                  # Show full details for unknown services
                  if (host == 'localhost' || host == '127.0.0.1') && port != 80 && port != 443
                    "HTTP #{method} localhost:#{port}#{path}"
                  elsif port == 443 || port == 80
                    "HTTP #{method} #{host}#{path}"
                  else
                    "HTTP #{method} #{host}:#{port}#{path}"
                  end
              end

              ::Rack::MiniProfiler.step(label) do
                super
              end
            end
          end
        else
          super
        end
      end

      private

      def identify_service(host, port, path)
        # DynamoDB
        return :dynamodb if host&.include?('dynamodb') ||
                            (host&.include?('amazonaws.com') && path == '/')

        # OpenSearch/Elasticsearch
        return :opensearch if port.to_s == '9200' ||
                              host&.include?('opensearch') ||
                              host&.include?('elasticsearch')

        # AWS Services
        return 'S3' if host&.include?('.s3.') || host&.include?('s3.amazonaws.com')
        return 'SQS' if host&.include?('sqs') && host&.include?('amazonaws.com')
        return 'SES' if host&.include?('email') && host&.include?('amazonaws.com')
        return 'SNS' if host&.include?('sns') && host&.include?('amazonaws.com')
        return 'Lambda' if host&.include?('lambda') && host&.include?('amazonaws.com')
        return 'CloudWatch' if host&.include?('monitoring') && host&.include?('amazonaws.com')

        # Third-party APIs
        return 'OpenAI' if host&.include?('api.openai.com')
        return 'Google' if host&.include?('googleapis.com')
        return 'Stripe' if host&.include?('stripe.com')
        return 'Twilio' if host&.include?('twilio.com')
        return 'SendGrid' if host&.include?('sendgrid')
        return 'GitHub' if host&.include?('github.com') || host&.include?('api.github.com')
        return 'Slack' if host&.include?('slack.com')
        return 'Webhook' if host&.include?('webhook')

        # No specific service identified
        nil
      end
    end

    # Prepend our module to Net::HTTP
    ::Net::HTTP.prepend(NetHttpSelectiveProfiler)

    Rails.logger.info 'Rack::MiniProfiler Net::HTTP selective profiling enabled'
  end
end

Clone this wiki locally