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

Inherits:
Object
  • Object
show all
Defined in:
lib/datadog/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.



34
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
# File 'lib/datadog/profiling/pprof/template.rb', line 34

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.



17
18
19
# File 'lib/datadog/profiling/pprof/template.rb', line 17

def builder
  @builder
end

#convertersObject (readonly)

Returns the value of attribute converters.



17
18
19
# File 'lib/datadog/profiling/pprof/template.rb', line 17

def converters
  @converters
end

#sample_type_mappingsObject (readonly)

Returns the value of attribute sample_type_mappings.



17
18
19
# File 'lib/datadog/profiling/pprof/template.rb', line 17

def sample_type_mappings
  @sample_type_mappings
end

Class Method Details

.for_event_classes(event_classes) ⇒ Object



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

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



74
75
76
# File 'lib/datadog/profiling/pprof/template.rb', line 74

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

#debug_statisticsObject



78
79
80
# File 'lib/datadog/profiling/pprof/template.rb', line 78

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

#to_pprof(start:, finish:) ⇒ Object



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

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