Module: Bitfab::Otel::Encoder

Defined in:
lib/bitfab/otel.rb

Overview

Turns finished carrier spans into the OTLP/JSON shapes Bitfab ingests.

Class Method Summary collapse

Class Method Details

.build_request(first, spans) ⇒ Object



703
704
705
706
707
708
709
710
711
712
713
714
# File 'lib/bitfab/otel.rb', line 703

def build_request(first, spans)
  scope = first.instrumentation_scope
  {
    "resourceSpans" => [{
      "resource" => {"attributes" => attributes(first.resource.attribute_enumerator.to_h)},
      "scopeSpans" => [{
        "scope" => {"name" => scope.name, "version" => scope.version || ""},
        "spans" => spans
      }]
    }]
  }
end

.encoded_size(value) ⇒ Object



716
717
718
# File 'lib/bitfab/otel.rb', line 716

def encoded_size(value)
  JSON.generate(value).bytesize
end

.error?(payload) ⇒ Boolean

Returns:

  • (Boolean)


767
768
769
770
771
772
773
# File 'lib/bitfab/otel.rb', line 767

def error?(payload)
  raw_span = payload["rawSpan"]
  return true if raw_span.is_a?(Hash) && !raw_span.dig("span_data", "error").nil?

  errors = payload["errors"]
  errors.is_a?(Array) && !errors.empty?
end

.span_name(operation, payload) ⇒ Object



741
742
743
744
745
746
747
748
749
750
# File 'lib/bitfab/otel.rb', line 741

def span_name(operation, payload)
  raw_span = payload["rawSpan"]
  if operation == "external_span" && raw_span.is_a?(Hash)
    name = raw_span.dig("span_data", "name")
    return name if name.is_a?(String)
  end
  return payload["traceFunctionKey"] if payload["traceFunctionKey"].is_a?(String)

  "bitfab.#{operation}"
end

.span_to_otlp(span) ⇒ Object



720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
# File 'lib/bitfab/otel.rb', line 720

def span_to_otlp(span)
  result = {
    "traceId" => span.hex_trace_id,
    "spanId" => span.hex_span_id,
    "name" => span.name,
    "kind" => SPAN_KINDS.fetch(span.kind, 1),
    "startTimeUnixNano" => (span.start_timestamp || 0).to_s,
    "endTimeUnixNano" => (span.end_timestamp || 0).to_s,
    "attributes" => attributes(span.attributes),
    "droppedAttributesCount" => dropped_count(span.total_recorded_attributes, span.attributes),
    "droppedEventsCount" => dropped_count(span.total_recorded_events, span.events),
    "droppedLinksCount" => dropped_count(span.total_recorded_links, span.links),
    "status" => status(span.status),
    "flags" => span.trace_flags.sampled? ? 1 : 0
  }
  result["parentSpanId"] = span.hex_parent_span_id unless span.parent_span_id == INVALID_SPAN_ID
  tracestate = span.tracestate&.to_s
  result["traceState"] = tracestate unless tracestate.nil? || tracestate.empty?
  result
end

.timestamp(payload, field) ⇒ Object



752
753
754
755
756
757
758
759
760
761
762
763
764
765
# File 'lib/bitfab/otel.rb', line 752

def timestamp(payload, field)
  raw = payload.dig("rawSpan", field) if payload["rawSpan"].is_a?(Hash)
  if raw.nil?
    raw_trace = payload["externalTrace"] || payload["rawTrace"]
    raw = raw_trace[field] if raw_trace.is_a?(Hash)
  end
  return Time.now unless raw.is_a?(String)

  begin
    Time.iso8601(raw)
  rescue ArgumentError
    Time.now
  end
end