Module: Datadog::DI Private

Defined in:
lib/datadog/di.rb,
lib/datadog/di/base.rb,
lib/datadog/di/error.rb,
lib/datadog/di/probe.rb,
lib/datadog/di/utils.rb,
lib/datadog/di/logger.rb,
lib/datadog/di/remote.rb,
lib/datadog/di/contrib.rb,
lib/datadog/di/redactor.rb,
lib/datadog/di/component.rb,
lib/datadog/di/extensions.rb,
lib/datadog/di/serializer.rb,
lib/datadog/di/code_tracker.rb,
lib/datadog/di/instrumenter.rb,
lib/datadog/di/configuration.rb,
lib/datadog/di/probe_builder.rb,
lib/datadog/di/probe_manager.rb,
lib/datadog/di/transport/http.rb,
lib/datadog/di/contrib/railtie.rb,
lib/datadog/di/transport/input.rb,
lib/datadog/di/transport/http/api.rb,
lib/datadog/di/transport/http/input.rb,
lib/datadog/di/probe_notifier_worker.rb,
lib/datadog/di/transport/diagnostics.rb,
lib/datadog/di/transport/http/client.rb,
lib/datadog/di/configuration/settings.rb,
lib/datadog/di/probe_notification_builder.rb,
lib/datadog/di/transport/http/diagnostics.rb

Overview

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

Namespace for Datadog dynamic instrumentation.

Defined Under Namespace

Modules: Configuration, Contrib, Extensions, ProbeBuilder, Remote, Transport, Utils Classes: CodeTracker, Component, Error, Instrumenter, Logger, Probe, ProbeManager, ProbeNotificationBuilder, ProbeNotifierWorker, Redactor, Serializer

Constant Summary collapse

LOCK =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Mutex.new

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.code_trackerObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



21
22
23
# File 'lib/datadog/di/base.rb', line 21

def code_tracker
  @code_tracker
end

Class Method Details

.activate_trackingObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Activates code tracking if possible.

This method does nothing if invoked in an environment that does not implement required trace points for code tracking (MRI Ruby < 2.6, JRuby) and rescues any exceptions that may be raised by downstream DI code.



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/datadog/di/base.rb', line 41

def activate_tracking
  # :script_compiled trace point was added in Ruby 2.6.
  return unless RUBY_VERSION >= '2.6'

  begin
    # Activate code tracking by default because line trace points will not work
    # without it.
    Datadog::DI.activate_tracking!
  rescue => exc
    if defined?(Datadog.logger)
      Datadog.logger.warn { "di: Failed to activate code tracking for DI: #{exc.class}: #{exc}" }
    else
      # We do not have Datadog logger potentially because DI code tracker is
      # being loaded early in application boot process and the rest of datadog
      # wasn't loaded yet. Output to standard error.
      warn("datadog: di: Failed to activate code tracking for DI: #{exc.class}: #{exc}")
    end
  end
end

.activate_tracking!Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Activates code tracking. Normally this method should be called when the application starts. If instrumenting third-party code, code tracking needs to be enabled before the third-party libraries are loaded. Any third-party code loaded before code tracking is activated will NOT be instrumentable using dynamic instrumentation.

TODO test that activating tracker multiple times preserves existing mappings in the registry



31
32
33
# File 'lib/datadog/di/base.rb', line 31

def activate_tracking!
  (@code_tracker ||= CodeTracker.new).start
end

.add_current_component(component) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

To avoid potential races with DI::Component being added and removed, we maintain a list of the components. Normally the list should contain either zero or one component depending on whether DI is enabled in Datadog configuration. However, if a new instance of DI::Component is created while the previous instance is still running, we are guaranteed to not end up with no component when one is running.



101
102
103
104
105
106
# File 'lib/datadog/di/base.rb', line 101

def add_current_component(component)
  LOCK.synchronize do
    @current_components ||= []
    @current_components << component
  end
end

.code_tracking_active?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns whether code tracking is available. This method should be used instead of querying #code_tracker because the latter one may be nil.

Returns:

  • (Boolean)


75
76
77
# File 'lib/datadog/di/base.rb', line 75

def code_tracking_active?
  code_tracker&.active? || false
end

.componentObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method is called from DI Remote handler to issue DI operations to the probe manager (add or remove probes).

When DI Remote is executing, Datadog.components should be initialized and we should be able to reference it to get to the DI component.

Given that we need the current_component anyway for code tracker, perhaps we should delete the component method and just use current_component in all cases.



48
49
50
# File 'lib/datadog/di.rb', line 48

def component
  Datadog.send(:components).dynamic_instrumentation
end

.current_componentObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

DI code tracker is instantiated globally before the regular set of components is created, but the code tracker needs to call out to the “current” DI component to perform instrumentation when application code is loaded. Because this call may happen prior to Datadog components having been initialized, we maintain the “current component” which contains a reference to the most recently instantiated DI::Component. This way, if a DI component hasn’t been instantiated, we do not try to reference Datadog.components. In other words, this method exists so that we never attempt to call Datadog.components from the code tracker.



89
90
91
92
93
# File 'lib/datadog/di/base.rb', line 89

def current_component
  LOCK.synchronize do
    @current_components&.last
  end
end

.deactivate_tracking!Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Deactivates code tracking. In normal usage of DI this method should never be called, however it is used by DI’s test suite to reset state for individual tests.

Note that deactivating tracking clears out the registry, losing the ability to look up files that have been loaded into the process already.



68
69
70
# File 'lib/datadog/di/base.rb', line 68

def deactivate_tracking!
  code_tracker&.stop
end

.enabled?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)


29
30
31
# File 'lib/datadog/di.rb', line 29

def enabled?
  Datadog.configuration.dynamic_instrumentation.enabled
end

.remove_current_component(component) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



108
109
110
111
112
# File 'lib/datadog/di/base.rb', line 108

def remove_current_component(component)
  LOCK.synchronize do
    @current_components&.delete(component)
  end
end