Class: Datadog::Profiling::Scheduler

Inherits:
Worker
  • Object
show all
Includes:
Workers::Polling
Defined in:
lib/ddtrace/profiling/scheduler.rb

Overview

Periodically (every DEFAULT_INTERVAL_SECONDS) takes data from the Recorder and pushes them to all configured Exporters. Runs on its own background thread.

Constant Summary collapse

DEFAULT_FLUSH_JITTER_MAXIMUM_SECONDS =

We sleep for at most this duration seconds before reporting data to avoid multi-process applications all reporting profiles at the exact same time

3

Constants included from Workers::Polling

Workers::Polling::SHUTDOWN_TIMEOUT

Instance Attribute Summary collapse

Attributes inherited from Worker

#task

Instance Method Summary collapse

Methods included from Workers::Polling

#enabled=, #enabled?, included, #stop

Constructor Details

#initialize(recorder, exporters, fork_policy: Workers::Async::Thread::FORK_POLICY_RESTART, interval: DEFAULT_INTERVAL_SECONDS, enabled: true) ⇒ Scheduler

Returns a new instance of Scheduler.



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

def initialize(
  recorder,
  exporters,
  fork_policy: Workers::Async::Thread::FORK_POLICY_RESTART, # Restart in forks by default
  interval: DEFAULT_INTERVAL_SECONDS,
  enabled: true
)
  @recorder = recorder
  @exporters = [exporters].flatten

  # Workers::Async::Thread settings
  self.fork_policy = fork_policy

  # Workers::IntervalLoop settings
  self.loop_base_interval = interval

  # Workers::Polling settings
  self.enabled = enabled
end

Instance Attribute Details

#exportersObject (readonly)

Returns the value of attribute exporters.



26
27
28
# File 'lib/ddtrace/profiling/scheduler.rb', line 26

def exporters
  @exporters
end

#recorderObject (readonly)

Returns the value of attribute recorder.



26
27
28
# File 'lib/ddtrace/profiling/scheduler.rb', line 26

def recorder
  @recorder
end

Instance Method Details

#after_forkObject



69
70
71
72
73
74
# File 'lib/ddtrace/profiling/scheduler.rb', line 69

def after_fork
  # Clear recorder's buffers by flushing events.
  # Objects from parent process will copy-on-write,
  # and we don't want to send events for the wrong process.
  recorder.flush
end

#loop_wait_before_first_iteration?Boolean

Configure Workers::IntervalLoop to not report immediately when scheduler starts

When a scheduler gets created (or reset), we don't want it to immediately try to flush; we want it to wait for the loop wait time first. This avoids an issue where the scheduler reported a mostly-empty profile if the application just started but this thread took a bit longer so there's already samples in the recorder.

Returns:

  • (Boolean)


81
82
83
# File 'lib/ddtrace/profiling/scheduler.rb', line 81

def loop_wait_before_first_iteration?
  true
end

#performObject



54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/ddtrace/profiling/scheduler.rb', line 54

def perform
  # A profiling flush may be called while the VM is shutting down, to report the last profile. When we do so,
  # we impose a strict timeout. This means this last profile may or may not be sent, depending on if the flush can
  # successfully finish in the strict timeout.
  # This can be somewhat confusing (why did it not get reported?), so let's at least log what happened.
  interrupted = true

  begin
    flush_and_wait
    interrupted = false
  ensure
    Datadog.logger.debug('#flush was interrupted or failed before it could complete') if interrupted
  end
end

#startObject



50
51
52
# File 'lib/ddtrace/profiling/scheduler.rb', line 50

def start
  perform
end

#work_pending?Boolean

Returns:

  • (Boolean)


85
86
87
# File 'lib/ddtrace/profiling/scheduler.rb', line 85

def work_pending?
  !recorder.empty?
end