Module: Datadog::Contrib::HTTP::Patcher

Defined in:
lib/ddtrace/contrib/http/patcher.rb

Overview

Patcher enables patching of ‘net/http’ module. This is used in monkey.rb to automatically apply patches

Class Method Summary collapse

Class Method Details

.patchObject

patch applies our patch if needed



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/ddtrace/contrib/http/patcher.rb', line 59

def patch
  unless @patched
    begin
      require 'uri'
      require 'ddtrace/pin'
      require 'ddtrace/monkey'
      require 'ddtrace/ext/app_types'
      require 'ddtrace/ext/http'
      require 'ddtrace/ext/net'
      require 'ddtrace/ext/distributed'

      patch_http()

      @patched = true
    rescue StandardError => e
      Datadog::Tracer.log.error("Unable to apply net/http integration: #{e}")
    end
  end
  @patched
end

.patch_httpObject

rubocop:disable Metrics/MethodLength rubocop:disable Metrics/BlockLength rubocop:disable Metrics/AbcSize



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/ddtrace/contrib/http/patcher.rb', line 88

def patch_http
  ::Net::HTTP.class_eval do
    alias_method :initialize_without_datadog, :initialize
    Datadog::Monkey.without_warnings do
      remove_method :initialize
    end

    def initialize(*args)
      pin = Datadog::Pin.new(SERVICE, app: APP, app_type: Datadog::Ext::AppTypes::WEB)
      pin.onto(self)
      initialize_without_datadog(*args)
    end

    alias_method :request_without_datadog, :request
    remove_method :request

    def request(req, body = nil, &block) # :yield: +response+
      pin = Datadog::Pin.get_from(self)
      return request_without_datadog(req, body, &block) unless pin && pin.tracer

      transport = pin.tracer.writer.transport
      return request_without_datadog(req, body, &block) if
        Datadog::Contrib::HTTP.should_skip_tracing?(req, @address, @port, transport, pin)

      pin.tracer.trace(NAME) do |span|
        begin
          span.service = pin.service
          span.span_type = Datadog::Ext::HTTP::TYPE

          span.resource = req.method
          # Using the method as a resource, as URL/path can trigger
          # a possibly infinite number of resources.
          span.set_tag(Datadog::Ext::HTTP::URL, req.path)
          span.set_tag(Datadog::Ext::HTTP::METHOD, req.method)

          unless Datadog::Contrib::HTTP.should_skip_distributed_tracing?(pin)
            req.add_field(Datadog::Ext::DistributedTracing::HTTP_HEADER_TRACE_ID, span.trace_id)
            req.add_field(Datadog::Ext::DistributedTracing::HTTP_HEADER_PARENT_ID, span.span_id)
          end
        rescue StandardError => e
          Datadog::Tracer.log.error("error preparing span for http request: #{e}")
        ensure
          response = request_without_datadog(req, body, &block)
        end
        span.set_tag(Datadog::Ext::HTTP::STATUS_CODE, response.code)
        if req.respond_to?(:uri) && req.uri
          span.set_tag(Datadog::Ext::NET::TARGET_HOST, req.uri.host)
          span.set_tag(Datadog::Ext::NET::TARGET_PORT, req.uri.port.to_s)
        else
          span.set_tag(Datadog::Ext::NET::TARGET_HOST, @address)
          span.set_tag(Datadog::Ext::NET::TARGET_PORT, @port.to_s)
        end

        case response.code.to_i / 100
        when 4
          span.set_error(response)
        when 5
          span.set_error(response)
        end

        response
      end
    end
  end
end

.patched?Boolean

patched? tells wether patch has been successfully applied

Returns:

  • (Boolean)


81
82
83
# File 'lib/ddtrace/contrib/http/patcher.rb', line 81

def patched?
  @patched
end