class Datadog::Profiling::Pprof::Builder

Accumulates profile data and produces a Perftools::Profiles::Profile

Constants

DEFAULT_ENCODING
DESC_FRAMES_OMITTED
DESC_FRAME_OMITTED

Attributes

functions[R]
locations[R]
mappings[R]
sample_types[R]
samples[R]
string_table[R]

Public Class Methods

new() click to toggle source
# File lib/ddtrace/profiling/pprof/builder.rb, line 25
def initialize
  @functions = MessageSet.new(1)
  @locations = initialize_locations_hash
  @mappings = MessageSet.new(1)
  @sample_types = MessageSet.new
  @samples = []
  @string_table = StringTable.new

  # Cache this proc, since it's pretty expensive to keep recreating it
  @build_function = method(:build_function).to_proc
end

Public Instance Methods

build_function(id, filename, function_name) click to toggle source
# File lib/ddtrace/profiling/pprof/builder.rb, line 103
def build_function(id, filename, function_name)
  Perftools::Profiles::Function.new(
    id: id,
    name: @string_table.fetch(function_name),
    filename: @string_table.fetch(filename)
  )
end
build_line(function_id, line_number) click to toggle source
# File lib/ddtrace/profiling/pprof/builder.rb, line 96
def build_line(function_id, line_number)
  Perftools::Profiles::Line.new(
    function_id: function_id,
    line: line_number
  )
end
build_location(id, backtrace_location) click to toggle source
# File lib/ddtrace/profiling/pprof/builder.rb, line 82
def build_location(id, backtrace_location)
  Perftools::Profiles::Location.new(
    id: id,
    line: [build_line(
      @functions.fetch(
        backtrace_location.path,
        backtrace_location.base_label,
        &@build_function
      ).id,
      backtrace_location.lineno
    )]
  )
end
build_locations(backtrace_locations, length) click to toggle source
# File lib/ddtrace/profiling/pprof/builder.rb, line 68
def build_locations(backtrace_locations, length)
  locations = backtrace_locations.collect { |backtrace_location| @locations[backtrace_location] }

  omitted = length - backtrace_locations.length

  # Add placeholder stack frame if frames were truncated
  if omitted > 0
    desc = omitted == 1 ? DESC_FRAME_OMITTED : DESC_FRAMES_OMITTED
    locations << @locations[Profiling::BacktraceLocation.new('', 0, "#{omitted} #{desc}")]
  end

  locations
end
build_mapping(id, filename) click to toggle source
# File lib/ddtrace/profiling/pprof/builder.rb, line 111
def build_mapping(id, filename)
  Perftools::Profiles::Mapping.new(
    id: id,
    filename: @string_table.fetch(filename)
  )
end
build_profile() click to toggle source
# File lib/ddtrace/profiling/pprof/builder.rb, line 50
def build_profile
  Perftools::Profiles::Profile.new(
    sample_type: @sample_types.messages,
    sample: @samples,
    mapping: @mappings.messages,
    location: @locations.values,
    function: @functions.messages,
    string_table: @string_table.strings
  )
end
build_value_type(type, unit) click to toggle source
# File lib/ddtrace/profiling/pprof/builder.rb, line 61
def build_value_type(type, unit)
  Perftools::Profiles::ValueType.new(
    type: @string_table.fetch(type),
    unit: @string_table.fetch(unit)
  )
end
encode_profile(profile) click to toggle source
# File lib/ddtrace/profiling/pprof/builder.rb, line 46
def encode_profile(profile)
  Perftools::Profiles::Profile.encode(profile).force_encoding(DEFAULT_ENCODING)
end
initialize_locations_hash() click to toggle source

The locations hash maps unique BacktraceLocation instances to their corresponding pprof Location objects; there's a 1:1 correspondence, since BacktraceLocations were already deduped

# File lib/ddtrace/profiling/pprof/builder.rb, line 39
def initialize_locations_hash
  sequence = Utils::Sequence.new(1)
  Hash.new do |locations_hash, backtrace_location|
    locations_hash[backtrace_location] = build_location(sequence.next, backtrace_location)
  end
end