Module: Datadog::Tracing::Contrib::HTTPX::Plugin::RequestTracer

Extended by:
Contrib::HttpAnnotationHelper
Defined in:
lib/httpx/adapters/datadog.rb

Constant Summary collapse

SPAN_REQUEST =
"httpx.request"

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.call(request) ⇒ Object

initializes tracing on the request.



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
# File 'lib/httpx/adapters/datadog.rb', line 41

def call(request)
  return unless configuration(request).enabled

  span = nil

  # request objects are reused, when already buffered requests get rerouted to a different
  # connection due to connection issues, or when they already got a response, but need to
  # be retried. In such situations, the original span needs to be extended for the former,
  # while a new is required for the latter.
  request.on(:idle) do
    span = nil
  end
  # the span is initialized when the request is buffered in the parser, which is the closest
  # one gets to actually sending the request.
  request.on(:headers) do
    next if span

    span = initialize_span(request, now)
  end

  request.on(:response) do |response|
    unless span
      next unless response.is_a?(::HTTPX::ErrorResponse) && response.error.respond_to?(:connection)

      # handles the case when the +error+ happened during name resolution, which means
      # that the tracing start point hasn't been triggered yet; in such cases, the approximate
      # initial resolving time is collected from the connection, and used as span start time,
      # and the tracing object in inserted before the on response callback is called.
      span = initialize_span(request, response.error.connection.init_time)

    end

    finish(response, span)
  end
end

.configuration(request) ⇒ Object



133
134
135
# File 'lib/httpx/adapters/datadog.rb', line 133

def configuration(request)
  Datadog.configuration.tracing[:httpx, request.uri.host]
end

.finish(response, span) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
# File 'lib/httpx/adapters/datadog.rb', line 77

def finish(response, span)
  if response.is_a?(::HTTPX::ErrorResponse)
    span.set_error(response.error)
  else
    span.set_tag(TAG_STATUS_CODE, response.status.to_s)

    span.set_error(::HTTPX::HTTPError.new(response)) if response.status >= 400 && response.status <= 599
  end

  span.finish
end

.initialize_span(request, start_time) ⇒ Object

return a span initialized with the @request state.



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
# File 'lib/httpx/adapters/datadog.rb', line 90

def initialize_span(request, start_time)
  verb = request.verb
  uri = request.uri

  config = configuration(request)

  span = create_span(request, config, start_time)

  span.resource = verb

  # Add additional request specific tags to the span.

  span.set_tag(TAG_URL, request.path)
  span.set_tag(TAG_METHOD, verb)

  span.set_tag(TAG_TARGET_HOST, uri.host)
  span.set_tag(TAG_TARGET_PORT, uri.port)

  # Tag as an external peer service
  span.set_tag(TAG_PEER_SERVICE, span.service)

  if config[:distributed_tracing]
    propagate_trace_http(
      Datadog::Tracing.active_trace,
      request.headers
    )
  end

  # Set analytics sample rate
  if Contrib::Analytics.enabled?(config[:analytics_enabled])
    Contrib::Analytics.set_sample_rate(span, config[:analytics_sample_rate])
  end

  span
rescue StandardError => e
  Datadog.logger.error("error preparing span for http request: #{e}")
  Datadog.logger.error(e.backtrace)
end

.nowObject



129
130
131
# File 'lib/httpx/adapters/datadog.rb', line 129

def now
  ::Datadog::Core::Utils::Time.now.utc
end

Instance Method Details

#create_span(request, configuration, start_time) ⇒ Object



142
143
144
145
146
147
148
149
# File 'lib/httpx/adapters/datadog.rb', line 142

def create_span(request, configuration, start_time)
  Datadog::Tracing.trace(
    SPAN_REQUEST,
    service: service_name(request.uri.host, configuration),
    type: TYPE_OUTBOUND,
    start_time: start_time
  )
end

#propagate_trace_http(trace, headers) ⇒ Object



138
139
140
# File 'lib/httpx/adapters/datadog.rb', line 138

def propagate_trace_http(trace, headers)
  Datadog::Tracing::Contrib::HTTP.inject(trace, headers)
end