Module: Datadog::Profiling::Component
- Defined in:
- lib/datadog/profiling/component.rb
Overview
Responsible for wiring up the Profiler for execution
Class Method Summary collapse
-
.build_profiler_component(settings:, agent_settings:, optional_tracer:, logger:) ⇒ Object
Passing in a
niltracer is supported and will disable the following profiling features: * Profiling in the trace viewer, as well as scoping a profile down to a span * Endpoint aggregation in the profiler UX, including normalization (resource per endpoint call).
Class Method Details
.build_profiler_component(settings:, agent_settings:, optional_tracer:, logger:) ⇒ Object
Passing in a nil tracer is supported and will disable the following profiling features:
- Profiling in the trace viewer, as well as scoping a profile down to a span
- Endpoint aggregation in the profiler UX, including normalization (resource per endpoint call)
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 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 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/datadog/profiling/component.rb', line 12 def self.build_profiler_component(settings:, agent_settings:, optional_tracer:, logger:) # rubocop:disable Metrics/MethodLength # Workaround for weird dependency direction: the Core::Configuration::Components class currently has a # dependency on individual products, in this case the Profiler. # (Note "currently": in the future we want to change this so core classes don't depend on specific products) # # If the current file included a `require 'datadog/profiler'` at its beginning, we would generate circular # requires when used from profiling: # # datadog/profiling # └─requires─> datadog/core # └─requires─> datadog/core/configuration/components # └─requires─> datadog/profiling # Loop! # # ...thus in #1998 we removed such a require. # # On the other hand, if datadog/core is loaded by a different product and no general `require 'datadog'` is # done, then profiling may not be loaded, and thus to avoid this issue we do a require here (which is a # no-op if profiling is already loaded). require_relative "../profiling" return [nil, {profiling_enabled: false}] unless settings.profiling.enabled && Profiling.supported? # Activate forking extensions Profiling::Tasks::Setup.new.run # NOTE: Please update the Initialization section of ProfilingDevelopment.md with any changes to this method no_signals_workaround_enabled = no_signals_workaround_enabled?(settings, logger) allocation_profiling_enabled = enable_allocation_profiling?(settings, logger) heap_sample_every = get_heap_sample_every(settings) heap_profiling_enabled = enable_heap_profiling?(settings, allocation_profiling_enabled, heap_sample_every, logger) heap_size_profiling_enabled = enable_heap_size_profiling?(settings, heap_profiling_enabled, logger) overhead_target_percentage = valid_overhead_target(settings.profiling.advanced.overhead_target_percentage, logger) upload_period_seconds = [60, settings.profiling.advanced.upload_period_seconds].max cpu_sampling_interval_ms = valid_cpu_sampling_interval(settings.profiling.advanced.experimental_cpu_sampling_interval_ms, logger) recorder = Datadog::Profiling::StackRecorder.new( alloc_samples_enabled: allocation_profiling_enabled, heap_samples_enabled: heap_profiling_enabled, heap_size_enabled: heap_size_profiling_enabled, heap_sample_every: heap_sample_every, heap_clean_after_gc_enabled: settings.profiling.advanced.heap_clean_after_gc_enabled, ) thread_context_collector = build_thread_context_collector(settings, recorder, optional_tracer) worker = Datadog::Profiling::Collectors::CpuAndWallTimeWorker.new( gc_profiling_enabled: enable_gc_profiling?(settings, logger), no_signals_workaround_enabled: no_signals_workaround_enabled, thread_context_collector: thread_context_collector, dynamic_sampling_rate_overhead_target_percentage: overhead_target_percentage, allocation_profiling_enabled: allocation_profiling_enabled, allocation_counting_enabled: settings.profiling.advanced.allocation_counting_enabled, gvl_profiling_enabled: enable_gvl_profiling?(settings, logger), sighandler_sampling_enabled: settings.profiling.advanced.sighandler_sampling_enabled, cpu_sampling_interval_ms: cpu_sampling_interval_ms, waiting_for_gvl_threshold_ns: settings.profiling.advanced.waiting_for_gvl_threshold_ns, ) = { no_signals_workaround_enabled: no_signals_workaround_enabled, heap_sample_every: heap_sample_every, }.freeze exporter = build_profiler_exporter(settings, recorder, worker, internal_metadata: ) transport = build_profiler_transport(settings, agent_settings) scheduler = Profiling::Scheduler.new(exporter: exporter, transport: transport, interval: upload_period_seconds) profiler = Profiling::Profiler.new(worker: worker, scheduler: scheduler) if dir_interruption_workaround_enabled?(settings, no_signals_workaround_enabled) Datadog::Profiling::Ext::DirMonkeyPatches.apply! end if can_apply_exec_monkey_patch?(settings) Datadog::Profiling::Ext::ExecMonkeyPatch.apply! end [profiler, {profiling_enabled: true}] rescue Exception => e # rubocop:disable Lint/RescueException logger.warn do "Failed to initialize profiling: #{e.class}: #{e.} " \ "Location: #{Array(e.backtrace).first}" end Datadog::Core::Telemetry::Logger.report(e, description: "Failed to initialize profiling") [nil, {profiling_enabled: false}] end |