# frozen_string_literal: true require_relative '../../transport/traces' require_relative '../../../core/transport/parcel' require_relative 'response' require_relative 'client' module Datadog module Tracing module Transport module IO # IO transport behavior for traces module Traces # Response from HTTP transport for traces class Response < IO::Response include Transport::Traces::Response def initialize(result, trace_count = 1) super(result) @trace_count = trace_count end end # Extensions for HTTP client module Client def send_traces(traces) # Build a request req = Transport::Traces::Request.new(Parcel.new(traces)) [send_request(req) do |out, request| # Encode trace data data = encode_data(encoder, request) # Write to IO result = if block_given? yield(out, data) else write_data(out, data) end # Generate response Traces::Response.new(result) end] end end # Encoder for IO-specific trace encoding # API compliant when used with {JSONEncoder}. module Encoder ENCODED_IDS = [ :trace_id, :span_id, :parent_id ].freeze # Encodes a list of traces def encode_traces(encoder, traces) trace_hashes = traces.map do |trace| encode_trace(trace) end # Wrap traces & encode them encoder.encode(traces: trace_hashes) end private def encode_trace(trace) # Convert each trace to hash trace.spans.map(&:to_hash).tap do |spans| # Convert IDs to hexadecimal spans.each do |span| ENCODED_IDS.each do |id| span[id] = span[id].to_s(16) if span.key?(id) end end end end end # Transfer object for list of traces class Parcel include Datadog::Core::Transport::Parcel include Encoder def count data.length end def encode_with(encoder) encode_traces(encoder, data) end end # Add traces behavior to transport components IO::Client.include(Traces::Client) end end end end end