Class: Datadog::HTTPTransport
- Inherits:
-
Object
- Object
- Datadog::HTTPTransport
- Defined in:
- lib/ddtrace/transport.rb
Overview
Transport class that handles the spans delivery to the local trace-agent. The class wraps a Net:HTTP instance so that the Transport is thread-safe. rubocop:disable Metrics/ClassLength
Constant Summary collapse
- DEFAULT_AGENT_HOST =
'127.0.0.1'.freeze
- DEFAULT_TRACE_AGENT_PORT =
'8126'.freeze
- DEPRECATION_WARNING =
%( Datadog::HTTPTransport is deprecated as of version 0.24.0. It has been replaced by Datadog::Transport:HTTP, which is the new default. You can create one with `Datadog::Transport::HTTP.default` Datadog::HTTPTransport will be REMOVED in version 0.25.0).freeze
- TIMEOUT =
seconds before the transport timeout
1- TRACE_COUNT_HEADER =
header containing the number of traces in a payload
'X-Datadog-Trace-Count'.freeze
- RUBY_INTERPRETER =
RUBY_VERSION > '1.9' ? RUBY_ENGINE + '-' + RUBY_PLATFORM : 'ruby-' + RUBY_PLATFORM
Instance Attribute Summary collapse
-
#hostname ⇒ Object
Returns the value of attribute hostname.
-
#port ⇒ Object
Returns the value of attribute port.
-
#traces_endpoint ⇒ Object
readonly
Returns the value of attribute traces_endpoint.
Instance Method Summary collapse
- #client_error?(code) ⇒ Boolean
-
#downgrade! ⇒ Object
Downgrade the connection to a compatibility version of the HTTPTransport; this method should target a stable API that works whatever is the agent or the tracing client versions.
-
#downgrade?(code) ⇒ Boolean
receiving a 404 means that we’re targeting an endpoint that is not available in the trace agent.
-
#handle_response(response) ⇒ Object
handles the server response; here you can log the trace-agent response or do something more complex to recover from a possible error.
- #informational?(code) ⇒ Boolean
-
#initialize(options = {}) ⇒ HTTPTransport
constructor
A new instance of HTTPTransport.
-
#post(url, data, count = nil) ⇒ Object
send data to the trace-agent; the method is thread-safe.
- #redirect?(code) ⇒ Boolean
-
#send(endpoint, data) ⇒ Object
route the send to the right endpoint.
- #server_error?(code) ⇒ Boolean
- #stats ⇒ Object
- #success?(code) ⇒ Boolean
Constructor Details
#initialize(options = {}) ⇒ HTTPTransport
Returns a new instance of HTTPTransport.
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/ddtrace/transport.rb', line 54 def initialize( = {}) # Log deprecation warning Datadog::Tracer.log.warn(DEPRECATION_WARNING) api_version = .fetch(:api_version, V3) @hostname = [:hostname] || ENV['DD_AGENT_HOST'] || DEFAULT_AGENT_HOST @port = [:port] || ENV['DD_TRACE_AGENT_PORT'] || DEFAULT_TRACE_AGENT_PORT @api = API.fetch(api_version) @encoder = [:encoder] || @api[:encoder] @response_callback = [:response_callback] # overwrite the Content-type with the one chosen in the Encoder @headers = .fetch(:headers, {}) @headers['Content-Type'] = @encoder.content_type @headers['Datadog-Meta-Lang'] = 'ruby' @headers['Datadog-Meta-Lang-Version'] = RUBY_VERSION @headers['Datadog-Meta-Lang-Interpreter'] = RUBY_INTERPRETER @headers['Datadog-Meta-Tracer-Version'] = Datadog::VERSION::STRING # stats @mutex = Mutex.new @count_success = 0 @count_client_error = 0 @count_server_error = 0 @count_internal_error = 0 @count_consecutive_errors = 0 end |
Instance Attribute Details
#hostname ⇒ Object
Returns the value of attribute hostname.
13 14 15 |
# File 'lib/ddtrace/transport.rb', line 13 def hostname @hostname end |
#port ⇒ Object
Returns the value of attribute port.
13 14 15 |
# File 'lib/ddtrace/transport.rb', line 13 def port @port end |
#traces_endpoint ⇒ Object (readonly)
Returns the value of attribute traces_endpoint.
14 15 16 |
# File 'lib/ddtrace/transport.rb', line 14 def traces_endpoint @traces_endpoint end |
Instance Method Details
#client_error?(code) ⇒ Boolean
153 154 155 |
# File 'lib/ddtrace/transport.rb', line 153 def client_error?(code) code.between?(400, 499) end |
#downgrade! ⇒ Object
Downgrade the connection to a compatibility version of the HTTPTransport; this method should target a stable API that works whatever is the agent or the tracing client versions.
131 132 133 134 135 136 137 138 139 |
# File 'lib/ddtrace/transport.rb', line 131 def downgrade! @mutex.synchronize do fallback_version = @api.fetch(:fallback) @api = API.fetch(fallback_version) @encoder = @api[:encoder] @headers['Content-Type'] = @encoder.content_type end end |
#downgrade?(code) ⇒ Boolean
receiving a 404 means that we’re targeting an endpoint that is not available in the trace agent. Usually this means that we’ve an up-to-date tracing client, while running an obsolete agent. receiving a 415 means that we’re using an unsupported content-type with an existing endpoint. Usually this means that we’re using a newer encoder with a previous endpoint. In both cases, we’re going to downgrade the transporter encoder so that it will target a stable API.
168 169 170 171 172 |
# File 'lib/ddtrace/transport.rb', line 168 def downgrade?(code) return unless @api[:fallback] code == 404 || code == 415 end |
#handle_response(response) ⇒ Object
handles the server response; here you can log the trace-agent response or do something more complex to recover from a possible error. This function is handled within the HTTP mutex.synchronize so it’s thread-safe.
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/ddtrace/transport.rb', line 177 def handle_response(response) status_code = response.code.to_i if success?(status_code) Datadog::Tracer.log.debug('Payload correctly sent to the trace agent.') @mutex.synchronize { @count_consecutive_errors = 0 } @mutex.synchronize { @count_success += 1 } elsif downgrade?(status_code) Datadog::Tracer.log.debug("calling the endpoint but received #{status_code}; downgrading the API") elsif client_error?(status_code) log_error_once("Client error: #{response.}") @mutex.synchronize { @count_client_error += 1 } elsif server_error?(status_code) log_error_once("Server error: #{response.}") end status_code rescue StandardError => e log_error_once(e.) @mutex.synchronize { @count_internal_error += 1 } 500 end |
#informational?(code) ⇒ Boolean
141 142 143 |
# File 'lib/ddtrace/transport.rb', line 141 def informational?(code) code.between?(100, 199) end |
#post(url, data, count = nil) ⇒ Object
send data to the trace-agent; the method is thread-safe
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/ddtrace/transport.rb', line 108 def post(url, data, count = nil) begin Datadog::Tracer.log.debug("Sending data from process: #{Process.pid}") headers = count.nil? ? {} : { TRACE_COUNT_HEADER => count.to_s } headers = headers.merge(@headers) request = Net::HTTP::Post.new(url, headers) request.body = data response = Net::HTTP.start(@hostname, @port, open_timeout: TIMEOUT, read_timeout: TIMEOUT) do |http| http.request(request) end handle_response(response) rescue StandardError => e log_error_once(e.) 500 end.tap do yield(response) if block_given? end end |
#redirect?(code) ⇒ Boolean
149 150 151 |
# File 'lib/ddtrace/transport.rb', line 149 def redirect?(code) code.between?(300, 399) end |
#send(endpoint, data) ⇒ Object
route the send to the right endpoint
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/ddtrace/transport.rb', line 84 def send(endpoint, data) case endpoint when :services return nil when :traces count = data.length payload = @encoder.encode_traces(data) status_code = post(@api[:traces_endpoint], payload, count) do |response| process_callback(:traces, response) end else Datadog::Tracer.log.error("Unsupported endpoint: #{endpoint}") return nil end if downgrade?(status_code) downgrade! send(endpoint, data) else status_code end end |
#server_error?(code) ⇒ Boolean
157 158 159 |
# File 'lib/ddtrace/transport.rb', line 157 def server_error?(code) code.between?(500, 599) end |
#stats ⇒ Object
201 202 203 204 205 206 207 208 209 210 |
# File 'lib/ddtrace/transport.rb', line 201 def stats @mutex.synchronize do { success: @count_success, client_error: @count_client_error, server_error: @count_server_error, internal_error: @count_internal_error } end end |
#success?(code) ⇒ Boolean
145 146 147 |
# File 'lib/ddtrace/transport.rb', line 145 def success?(code) code.between?(200, 299) end |