class OpenCensus::Tags::Formatters::Binary

This formatter serializes and deserializes tags context according to the OpenCensus' BinaryEncoding specification. See [documentation](github.com/census-instrumentation/opencensus-specs/blob/master/encodings/BinaryEncoding.md).

@example Serialize

formatter = OpenCensus::Tags::Formatters::Binary.new

tag_map = OpenCensus::Tags::TagMap.new({"key1“ => "val1”}) binary = formatter.serialize tag_map # “x00x00x04key1x04val1”

@example Deserialize

formatter = OpenCensus::Tags::Formatters::Binary.new

binary = “x00x00x04key1x04val1” tag_map = formatter.deserialize binary

Constants

TAG_FIELD_ID

@private

Tag field id

TAG_MAP_SERIALIZED_SIZE_LIMIT

@private

Serialized tag context limit

VERSION_ID

@private

Seralization version

Public Instance Methods

deserialize(binary) click to toggle source

Deserialize binary data into a TagMap object.

@param [String] binary @return [TagMap] @raise [BinaryFormatterError] If deserialized version id not valid or tag key, value size in varint more then then unsigned int32.

# File lib/opencensus/tags/formatters/binary.rb, line 70
def deserialize binary
  return TagMap.new if binary.nil? || binary.empty?

  io = StringIO.new binary
  version_id = io.getc.unpack("C").first
  unless version_id == VERSION_ID
    raise BinaryFormatterError, "invalid version id"
  end

  tag_map = TagMap.new

  loop do
    break if io.eof?
    tag_field_id = io.getc.unpack("C").first
    break unless tag_field_id == TAG_FIELD_ID

    key_length = varint_to_int io
    key = io.gets key_length
    value_length = varint_to_int io
    value = io.gets value_length
    tag_map[key] = value
  end

  io.close
  tag_map
end
serialize(tags_context) click to toggle source

Serialize TagMap object

@param [TagMap] tags_context

# File lib/opencensus/tags/formatters/binary.rb, line 48
def serialize tags_context
  binary = [int_to_varint(VERSION_ID)]

  tags_context.each do |key, value|
    binary << int_to_varint(TAG_FIELD_ID)
    binary << int_to_varint(key.length)
    binary << key.encode(Encoding::UTF_8)
    binary << int_to_varint(value ? value.length : 0)
    binary << value.to_s.encode(Encoding::UTF_8)
  end

  binary = binary.join
  binary.length > TAG_MAP_SERIALIZED_SIZE_LIMIT ? nil : binary
end

Private Instance Methods

int_to_varint(int_val) click to toggle source

Convert integer to Varint. @see developers.google.com/protocol-buffers/docs/encoding#varints

@param [Integer] int_val @return [String]

# File lib/opencensus/tags/formatters/binary.rb, line 104
def int_to_varint int_val
  result = []
  loop do
    bits = int_val & 0x7F
    int_val >>= 7
    if int_val.zero?
      result << bits
      break
    else
      result << (0x80 | bits)
    end
  end
  result.pack "C*"
end
varint_to_int(io) click to toggle source

Convert Varint bytes format to integer @see developers.google.com/protocol-buffers/docs/encoding#varints

@param [StringIO] io @return [Integer] @raise [BinaryFormatterError] If varint size more then unsigned int32

# File lib/opencensus/tags/formatters/binary.rb, line 126
def varint_to_int io
  int_val = 0
  shift = 0

  loop do
    raise BinaryFormatterError, "varint too long" if shift >= 32
    byte = io.getbyte
    int_val |= (byte & 0x7F) << shift
    shift += 7
    return int_val if (byte & 0x80).zero?
  end
end