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
- 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.
-
#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.
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/ddtrace/transport.rb', line 22 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 @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 end |
Instance Attribute Details
#hostname ⇒ Object
Returns the value of attribute hostname.
12 13 14 |
# File 'lib/ddtrace/transport.rb', line 12 def hostname @hostname end |
#port ⇒ Object
Returns the value of attribute port.
12 13 14 |
# File 'lib/ddtrace/transport.rb', line 12 def port @port end |
#services_endpoint ⇒ Object (readonly)
Returns the value of attribute services_endpoint.
13 14 15 |
# File 'lib/ddtrace/transport.rb', line 13 def services_endpoint @services_endpoint end |
#traces_endpoint ⇒ Object (readonly)
Returns the value of attribute traces_endpoint.
13 14 15 |
# File 'lib/ddtrace/transport.rb', line 13 def traces_endpoint @traces_endpoint end |
Instance Method Details
#client_error?(code) ⇒ Boolean
106 107 108 |
# File 'lib/ddtrace/transport.rb', line 106 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.
86 87 88 89 90 91 92 |
# File 'lib/ddtrace/transport.rb', line 86 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.
121 122 123 |
# File 'lib/ddtrace/transport.rb', line 121 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.
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/ddtrace/transport.rb', line 128 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
94 95 96 |
# File 'lib/ddtrace/transport.rb', line 94 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
69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/ddtrace/transport.rb', line 69 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
102 103 104 |
# File 'lib/ddtrace/transport.rb', line 102 def redirect?(code) code.between?(300, 399) end |
#send(endpoint, data) ⇒ Object
route the send to the right endpoint
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/ddtrace/transport.rb', line 47 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
110 111 112 |
# File 'lib/ddtrace/transport.rb', line 110 def server_error?(code) code.between?(500, 599) end |
#stats ⇒ Object
151 152 153 154 155 156 157 158 159 160 |
# File 'lib/ddtrace/transport.rb', line 151 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
98 99 100 |
# File 'lib/ddtrace/transport.rb', line 98 def success?(code) code.between?(200, 299) end |