Module: Datadog::Contrib::HTTP::Instrumentation::InstanceMethods

Includes:
Datadog::Contrib::HttpAnnotationHelper
Defined in:
lib/ddtrace/contrib/http/instrumentation.rb

Overview

InstanceMethods - implementing instrumentation

Instance Method Summary collapse

Methods included from Datadog::Contrib::HttpAnnotationHelper

#service_name

Instance Method Details

#annotate_span_with_error!(span, error) ⇒ Object



105
106
107
# File 'lib/ddtrace/contrib/http/instrumentation.rb', line 105

def annotate_span_with_error!(span, error)
  span.set_error(error)
end

#annotate_span_with_request!(span, request, request_options) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/ddtrace/contrib/http/instrumentation.rb', line 79

def annotate_span_with_request!(span, request, request_options)
  span.set_tag(Datadog::Ext::HTTP::URL, request.path)
  span.set_tag(Datadog::Ext::HTTP::METHOD, request.method)

  host, port = host_and_port(request)
  span.set_tag(Datadog::Ext::NET::TARGET_HOST, host)
  span.set_tag(Datadog::Ext::NET::TARGET_PORT, port.to_s)

  # Tag as an external peer service
  span.set_tag(Datadog::Ext::Integration::TAG_PEER_SERVICE, span.service)

  # Set analytics sample rate
  set_analytics_sample_rate(span, request_options)
end

#annotate_span_with_response!(span, response) ⇒ Object



94
95
96
97
98
99
100
101
102
103
# File 'lib/ddtrace/contrib/http/instrumentation.rb', line 94

def annotate_span_with_response!(span, response)
  return unless response && response.code

  span.set_tag(Datadog::Ext::HTTP::STATUS_CODE, response.code)

  case response.code.to_i
  when 400...599
    span.set_error(response)
  end
end

#datadog_pin(config = ) ⇒ Object



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
# File 'lib/ddtrace/contrib/http/instrumentation.rb', line 115

def datadog_pin(config = Datadog.configuration[:http])
  service = config[:service_name]
  tracer = config[:tracer]

  @datadog_pin ||= Datadog::Pin.new(
    service,
    app: Ext::APP,
    app_type: Datadog::Ext::HTTP::TYPE_OUTBOUND,
    tracer: -> { config[:tracer] }
  )

  # this shockingly poor code exists to solve the case where someone
  # calls datadog_pin on this object before running a request, which
  # would cause the :default config to be used. If a request is then
  # run for a hostname that matches a different configuration, we
  # would use the wrong configs since the pin is memoized.
  # The solution is to detect if we are using the default config and
  # apply the new config if necessary, while still allowing custom
  # values to be supplied
  if @datadog_pin.service_name == default_datadog_pin.service_name && @datadog_pin.service_name != service
    @datadog_pin.service = service
  end
  if @datadog_pin.tracer == default_datadog_pin.tracer && @datadog_pin.tracer != tracer
    @datadog_pin.tracer = tracer
  end

  @datadog_pin
end

#default_datadog_pinObject



144
145
146
147
148
149
150
151
152
153
# File 'lib/ddtrace/contrib/http/instrumentation.rb', line 144

def default_datadog_pin
  config = Datadog.configuration[:http]
  service = config[:service_name]
  @default_datadog_pin ||= Datadog::Pin.new(
    service,
    app: Ext::APP,
    app_type: Datadog::Ext::HTTP::TYPE_OUTBOUND,
    tracer: -> { config[:tracer] }
  )
end

#request(req, body = nil, &block) ⇒ Object

:yield: +response+



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/ddtrace/contrib/http/instrumentation.rb', line 37

def request(req, body = nil, &block)
  host, = host_and_port(req)
  request_options = datadog_configuration(host)
  pin = datadog_pin(request_options)
  return super(req, body, &block) unless pin && pin.tracer

  return super(req, body, &block) if Datadog::Contrib::HTTP.should_skip_tracing?(req, pin.tracer)

  pin.tracer.trace(Ext::SPAN_REQUEST, on_error: method(:annotate_span_with_error!)) do |span|
    begin
      # even though service_name might already be in request_options,
      # we need to capture the name from the pin since it could be
      # overridden
      request_options[:service_name] = pin.service_name
      span.service = service_name(host, request_options)
      span.span_type = Datadog::Ext::HTTP::TYPE_OUTBOUND
      span.resource = req.method

      if pin.tracer.enabled && !Datadog::Contrib::HTTP.should_skip_distributed_tracing?(pin)
        Datadog::HTTPPropagator.inject!(span.context, req)
      end

      # Add additional request specific tags to the span.
      annotate_span_with_request!(span, req, request_options)
    rescue StandardError => e
      Datadog.logger.error("error preparing span for http request: #{e}")
    ensure
      response = super(req, body, &block)
    end

    # Add additional response specific tags to the span.
    annotate_span_with_response!(span, response)

    # Invoke hook, if set.
    unless Contrib::HTTP::Instrumentation.after_request.nil?
      Contrib::HTTP::Instrumentation.after_request.call(span, self, req, response)
    end

    response
  end
end

#set_analytics_sample_rate(span, request_options) ⇒ Object



109
110
111
112
113
# File 'lib/ddtrace/contrib/http/instrumentation.rb', line 109

def set_analytics_sample_rate(span, request_options)
  return unless analytics_enabled?(request_options)

  Contrib::Analytics.set_sample_rate(span, analytics_sample_rate(request_options))
end