Class: Datadog::Profiling::StackRecorder

Inherits:
Object
  • Object
show all
Defined in:
lib/datadog/profiling/stack_recorder.rb,
ext/datadog_profiling_native_extension/stack_recorder.c

Overview

Stores stack samples in a native libdatadog data structure and expose Ruby-level serialization APIs Note that ‘record_sample` is only accessible from native code. Methods prefixed with native are implemented in `stack_recorder.c`

Defined Under Namespace

Modules: Testing

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(cpu_time_enabled:, alloc_samples_enabled:, heap_samples_enabled:, heap_size_enabled:, heap_sample_every:, timeline_enabled:) ⇒ StackRecorder

Returns a new instance of StackRecorder.



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/datadog/profiling/stack_recorder.rb', line 7

def initialize(
  cpu_time_enabled:, alloc_samples_enabled:, heap_samples_enabled:, heap_size_enabled:,
  heap_sample_every:, timeline_enabled:
)
  # This mutex works in addition to the fancy C-level mutexes we have in the native side (see the docs there).
  # It prevents multiple Ruby threads calling serialize at the same time -- something like
  # `10.times { Thread.new { stack_recorder.serialize } }`.
  # This isn't something we expect to happen normally, but because it would break the assumptions of the
  # C-level mutexes (that there is a single serializer thread), we add it here as an extra safeguard against it
  # accidentally happening.
  @no_concurrent_synchronize_mutex = Mutex.new

  self.class._native_initialize(
    self,
    cpu_time_enabled,
    alloc_samples_enabled,
    heap_samples_enabled,
    heap_size_enabled,
    heap_sample_every,
    timeline_enabled,
  )
end

Class Method Details

._native_initializeObject



237
238
239
240
241
242
243
244
245
246
# File 'ext/datadog_profiling_native_extension/stack_recorder.c', line 237

static VALUE _native_initialize(
  DDTRACE_UNUSED VALUE _self,
  VALUE recorder_instance,
  VALUE cpu_time_enabled,
  VALUE alloc_samples_enabled,
  VALUE heap_samples_enabled,
  VALUE heap_size_enabled,
  VALUE heap_sample_every,
  VALUE timeline_enabled
);

._native_reset_after_forkObject



258
# File 'ext/datadog_profiling_native_extension/stack_recorder.c', line 258

static VALUE _native_reset_after_fork(DDTRACE_UNUSED VALUE self, VALUE recorder_instance);

._native_serializeObject



247
# File 'ext/datadog_profiling_native_extension/stack_recorder.c', line 247

static VALUE _native_serialize(VALUE self, VALUE recorder_instance);

._native_statsObject



269
# File 'ext/datadog_profiling_native_extension/stack_recorder.c', line 269

static VALUE _native_stats(DDTRACE_UNUSED VALUE self, VALUE instance);

Instance Method Details

#reset_after_forkObject



62
63
64
# File 'lib/datadog/profiling/stack_recorder.rb', line 62

def reset_after_fork
  self.class._native_reset_after_fork(self)
end

#serializeObject



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/datadog/profiling/stack_recorder.rb', line 30

def serialize
  status, result = @no_concurrent_synchronize_mutex.synchronize { self.class._native_serialize(self) }

  if status == :ok
    start, finish, encoded_pprof, profile_stats = result

    Datadog.logger.debug { "Encoded profile covering #{start.iso8601} to #{finish.iso8601}" }

    [start, finish, encoded_pprof, profile_stats]
  else
    error_message = result

    Datadog.logger.error("Failed to serialize profiling data: #{error_message}")

    nil
  end
end

#serialize!Object



48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/datadog/profiling/stack_recorder.rb', line 48

def serialize!
  status, result = @no_concurrent_synchronize_mutex.synchronize { self.class._native_serialize(self) }

  if status == :ok
    _start, _finish, encoded_pprof = result

    encoded_pprof
  else
    error_message = result

    raise("Failed to serialize profiling data: #{error_message}")
  end
end

#statsObject



66
67
68
# File 'lib/datadog/profiling/stack_recorder.rb', line 66

def stats
  self.class._native_stats(self)
end