Class: Datadog::Profiling::Pprof::Template

Inherits:
Object
  • Object
show all
Defined in:
lib/ddtrace/profiling/pprof/template.rb

Overview

Converts a collection of profiling events into a Perftools::Profiles::Profile

Defined Under Namespace

Classes: NoProfilingEventConversionError, UnknownSampleTypeMappingError

Constant Summary collapse

DEFAULT_MAPPINGS =
{
  Events::StackSample => Pprof::StackSample
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(mappings) ⇒ Template

Returns a new instance of Template.



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/ddtrace/profiling/pprof/template.rb', line 35

def initialize(mappings)
  @builder = Builder.new
  @converters = Hash.new { |_h, event_class| raise NoProfilingEventConversionError, event_class }
  @sample_type_mappings = Hash.new { |_h, type| raise UnknownSampleTypeMappingError, type }

  # Add default mapping
  builder.mappings.fetch($PROGRAM_NAME, &builder.method(:build_mapping))

  # Combine all sample types from each converter class
  types = mappings.values.each_with_object({}) do |converter_class, t|
    t.merge!(converter_class.sample_value_types)
  end

  # Build the sample types into sample type objects
  types.each do |type_name, type_args|
    index = nil

    sample_type = builder.sample_types.fetch(*type_args) do |id, type, unit|
      index = id
      builder.build_value_type(type, unit)
    end

    # Create mapping between the type and index to which its assigned.
    # Do this for faster lookup while building profile sample values.
    sample_type_mappings[type_name] = index || builder.sample_types.messages.index(sample_type)
  end

  # Freeze them so they can't be modified.
  # We don't want the number of sample types to vary between samples within the same profile.
  builder.sample_types.freeze
  sample_type_mappings.freeze

  # Add converters
  mappings.each do |event_class, converter_class|
    converters[event_class] = converter_class.new(builder, sample_type_mappings)
  end

  converters.freeze
end

Instance Attribute Details

#builderObject (readonly)

Returns the value of attribute builder.



18
19
20
# File 'lib/ddtrace/profiling/pprof/template.rb', line 18

def builder
  @builder
end

#convertersObject (readonly)

Returns the value of attribute converters.



18
19
20
# File 'lib/ddtrace/profiling/pprof/template.rb', line 18

def converters
  @converters
end

#sample_type_mappingsObject (readonly)

Returns the value of attribute sample_type_mappings.



18
19
20
# File 'lib/ddtrace/profiling/pprof/template.rb', line 18

def sample_type_mappings
  @sample_type_mappings
end

Class Method Details

.for_event_classes(event_classes) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
# File 'lib/ddtrace/profiling/pprof/template.rb', line 23

def self.for_event_classes(event_classes)
  # Build a map of event class --> converter class
  mappings = event_classes.each_with_object({}) do |event_class, m|
    converter_class = DEFAULT_MAPPINGS[event_class]
    raise NoProfilingEventConversionError, event_class unless converter_class

    m[event_class] = converter_class
  end

  new(mappings)
end

Instance Method Details

#add_events!(event_class, events) ⇒ Object



75
76
77
# File 'lib/ddtrace/profiling/pprof/template.rb', line 75

def add_events!(event_class, events)
  converters[event_class].add_events!(events)
end

#debug_statisticsObject



79
80
81
# File 'lib/ddtrace/profiling/pprof/template.rb', line 79

def debug_statistics
  converters.values.map(&:debug_statistics).join(', ')
end

#to_pprof(start:, finish:) ⇒ Object



83
84
85
86
87
88
89
# File 'lib/ddtrace/profiling/pprof/template.rb', line 83

def to_pprof(start:, finish:)
  profile = builder.build_profile(start: start, finish: finish)
  data = builder.encode_profile(profile)
  types = sample_type_mappings.keys

  Payload.new(data, types)
end