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.
Constant Summary collapse
- TIMEOUT =
seconds before the transport timeout
1- TRACE_COUNT_HEADER =
header containing the number of traces in a payload
'X-Datadog-Trace-Count'.freeze
Instance Attribute Summary collapse
-
#hostname ⇒ Object
Returns the value of attribute hostname.
-
#port ⇒ Object
Returns the value of attribute port.
-
#services_endpoint ⇒ Object
readonly
Returns the value of attribute services_endpoint.
-
#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(hostname, port, 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(hostname, port, options = {}) ⇒ HTTPTransport
Returns a new instance of HTTPTransport.
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/ddtrace/transport.rb', line 20 def initialize(hostname, port, = {}) @hostname = hostname @port = port @traces_endpoint = '/v0.3/traces'.freeze @services_endpoint = '/v0.3/services'.freeze @compatibility_mode = false @encoder = .fetch(:encoder, Datadog::Encoding::MsgpackEncoder.new()) # overwrite the Content-type with the one chosen in the Encoder @headers = .fetch(:headers, {}) @headers['Content-Type'] = @encoder.content_type # stats @mutex = Mutex.new @count_success = 0 @count_client_error = 0 @count_server_error = 0 @count_internal_error = 0 end |
Instance Attribute Details
#hostname ⇒ Object
Returns the value of attribute hostname.
11 12 13 |
# File 'lib/ddtrace/transport.rb', line 11 def hostname @hostname end |
#port ⇒ Object
Returns the value of attribute port.
11 12 13 |
# File 'lib/ddtrace/transport.rb', line 11 def port @port end |
#services_endpoint ⇒ Object (readonly)
Returns the value of attribute services_endpoint.
12 13 14 |
# File 'lib/ddtrace/transport.rb', line 12 def services_endpoint @services_endpoint end |
#traces_endpoint ⇒ Object (readonly)
Returns the value of attribute traces_endpoint.
12 13 14 |
# File 'lib/ddtrace/transport.rb', line 12 def traces_endpoint @traces_endpoint end |
Instance Method Details
#client_error?(code) ⇒ Boolean
100 101 102 |
# File 'lib/ddtrace/transport.rb', line 100 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.
80 81 82 83 84 85 86 |
# File 'lib/ddtrace/transport.rb', line 80 def downgrade! @compatibility_mode = true @traces_endpoint = '/v0.2/traces'.freeze @services_endpoint = '/v0.2/services'.freeze @encoder = Datadog::Encoding::JSONEncoder.new() @headers['Content-Type'] = @encoder.content_type 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.
115 116 117 |
# File 'lib/ddtrace/transport.rb', line 115 def downgrade?(code) 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.
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/ddtrace/transport.rb', line 122 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_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) Datadog::Tracer.log.error("Client error: #{response.}") @mutex.synchronize { @count_client_error += 1 } elsif server_error?(status_code) Datadog::Tracer.log.error("Server error: #{response.}") @mutex.synchronize { @count_server_error += 1 } end status_code rescue StandardError => e Datadog::Tracer.log.error(e.) @mutex.synchronize { @count_internal_error += 1 } 500 end |
#informational?(code) ⇒ Boolean
88 89 90 |
# File 'lib/ddtrace/transport.rb', line 88 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
63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/ddtrace/transport.rb', line 63 def post(url, data, count = nil) 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, read_timeout: TIMEOUT) { |http| http.request(request) } handle_response(response) rescue StandardError => e Datadog::Tracer.log.error(e.) 500 end |
#redirect?(code) ⇒ Boolean
96 97 98 |
# File 'lib/ddtrace/transport.rb', line 96 def redirect?(code) code.between?(300, 399) end |
#send(endpoint, data) ⇒ Object
route the send to the right endpoint
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/ddtrace/transport.rb', line 41 def send(endpoint, data) case endpoint when :services payload = @encoder.encode_services(data) status_code = post(@services_endpoint, payload) when :traces count = data.length payload = @encoder.encode_traces(data) status_code = post(@traces_endpoint, payload, count) else Datadog::Tracer.log.error("Unsupported endpoint: #{endpoint}") return nil end return status_code unless downgrade?(status_code) && !@compatibility_mode # the API endpoint is not available so we should downgrade the connection and re-try the call downgrade! send(endpoint, data) end |
#server_error?(code) ⇒ Boolean
104 105 106 |
# File 'lib/ddtrace/transport.rb', line 104 def server_error?(code) code.between?(500, 599) end |
#stats ⇒ Object
145 146 147 148 149 150 151 152 153 154 |
# File 'lib/ddtrace/transport.rb', line 145 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
92 93 94 |
# File 'lib/ddtrace/transport.rb', line 92 def success?(code) code.between?(200, 299) end |