Module: Datadog::Profiling::Ext::CThread

Defined in:
lib/ddtrace/profiling/ext/cthread.rb

Overview

Extension used to enable CPU-time profiling via use of pthread’s ‘getcpuclockid`.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#pthread_thread_idObject (readonly)

Returns the value of attribute pthread_thread_id.



69
70
71
# File 'lib/ddtrace/profiling/ext/cthread.rb', line 69

def pthread_thread_id
  @pthread_thread_id
end

Class Method Details

.prepended(base) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
# File 'lib/ddtrace/profiling/ext/cthread.rb', line 39

def self.prepended(base)
  # Threads that have already been created, will not have resolved
  # a thread/clock ID. This is because these IDs can only be resolved
  # from within the thread's execution context, which we do not control.
  #
  # We can mitigate this for the current thread via #update_native_ids,
  # since we are currently running within its execution context. We cannot
  # do this for any other threads that may have been created already.
  # (This is why it's important that CThread is applied before anything else runs.)
  base.current.send(:update_native_ids) if base.current.is_a?(CThread)
end

Instance Method Details

#cpu_time(unit = :float_second) ⇒ Object



94
95
96
# File 'lib/ddtrace/profiling/ext/cthread.rb', line 94

def cpu_time(unit = :float_second)
  ::Process.clock_gettime(clock_id, unit) if clock_id
end

#cpu_time_instrumentation_installed?Boolean

Returns:

  • (Boolean)


98
99
100
101
102
103
104
105
106
# File 'lib/ddtrace/profiling/ext/cthread.rb', line 98

def cpu_time_instrumentation_installed?
  # If this thread was started before this module was added to Thread OR if something caused the initialize
  # method above not to be properly called on new threads, this instance variable is never defined (never set to
  # any value at all, including nil).
  #
  # Thus, we can use @clock_id as a canary to detect a thread that has missing instrumentation, because we
  # know that in initialize above we always set this variable to nil.
  defined?(@clock_id) != nil
end

#initialize(*args) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/ddtrace/profiling/ext/cthread.rb', line 76

def initialize(*args)
  @pid = ::Process.pid
  @pthread_thread_id = nil
  @clock_id = nil

  # Wrap the work block with our own
  # so we can retrieve the native thread ID within the thread's context.
  wrapped_block = proc do |*t_args|
    # Set native thread ID & clock ID
    update_native_ids
    yield(*t_args)
  end
  wrapped_block.ruby2_keywords if wrapped_block.respond_to?(:ruby2_keywords, true)

  super(*args, &wrapped_block)
end