Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
c297bba
Revert "Default DD_SYMBOL_DATABASE_UPLOAD_ENABLED to false"
p-datadog May 27, 2026
94c1d04
Default symbol_database.enabled to dynamic_instrumentation.enabled
p-ddsign May 28, 2026
9554612
Guard symbol_database default against DI extension not being loaded
p-ddsign May 28, 2026
af25895
SymDB: gate default on DI environment readiness, not just DI setting
p-ddsign Jun 10, 2026
a6bce3f
Merge branch 'master' into revert-5818-claude/symdb-default-off
p-datadog Jun 15, 2026
cf2496c
Stub DI::Component.environment_supported? in symdb default test
p-ddsign Jun 15, 2026
95c0d51
fix comments
Jun 23, 2026
69c8e82
Fix typo, drop defensive load-order guards from symbol_database default
p-ddsign Jun 23, 2026
f6eca7d
Fix symbol_database.enabled default raising when only datadog/core is…
p-ddsign Jun 23, 2026
0d30736
Correct NULL_LOGGER comment: drop inaccurate ordering claim
p-ddsign Jun 24, 2026
4e76e53
Revert "Fix symbol_database.enabled default raising when only datadog…
p-ddsign Jun 24, 2026
a512684
Remove SymbolDatabase settings group registration from core Settings
p-ddsign Jun 24, 2026
c52fd6e
Register symbol_database settings on the DI load path, not in core
p-ddsign Jun 24, 2026
63a879b
Merge branch 'master' into revert-5818-claude/symdb-default-off
p-datadog Jun 24, 2026
1d605df
Drop negative-fact comment from SymbolDatabase::Extensions
p-ddsign Jun 24, 2026
888f78d
Resolve symbol_database.enabled as a nil tri-state in core orchestration
p-ddsign Jun 25, 2026
e3a9016
ai slop
Jun 30, 2026
e8c83fd
Use let block instead of settings mutation for remote-enabled context
p-ddsign Jun 30, 2026
41a06d4
Resolve symbol_database enablement in orchestration, gated on DI runtime
p-ddsign Jun 30, 2026
6360299
Advertise symbol database RC product independently of DI
p-ddsign Jun 30, 2026
ceb3af0
Merge remote-tracking branch 'origin/master' into revert-5818-claude/…
p-ddsign Jun 30, 2026
3e321d2
Inline symbol database enablement check at the build site
p-ddsign Jun 30, 2026
118986e
Rename symbol-database resolver and inline capabilities check
p-ddsign Jun 30, 2026
9884fcb
Deduplicate symbol_database.enabled tri-state resolution
p-ddsign Jun 30, 2026
5cd9e0b
Trim resolve_enabled comment
p-ddsign Jun 30, 2026
4f9e8ce
Fix capabilities symbol-database fallback to mirror DI advertising
p-ddsign Jun 30, 2026
bcb9cf9
Update docs/GettingStarted.md
p-datadog Jul 1, 2026
96577a6
Gate Symbol Database upload on Dynamic Instrumentation being active
p-ddsign Jul 1, 2026
d3808c1
Update Symbol Database docs for DI-active upload gating
p-ddsign Jul 1, 2026
cbe74e8
Add specs for Symbol Database DI-active upload gate
p-ddsign Jul 1, 2026
e4f475c
Trim redundant sentences from Symbol Database enabling docs
p-ddsign Jul 1, 2026
6f1783b
Drop test reference from di_active param doc
p-ddsign Jul 1, 2026
3f2439b
Merge branch 'master' into revert-5818-claude/symdb-default-off
p-datadog Jul 1, 2026
6864071
Test Symbol Database upload replay on DI implicit enablement
p-ddsign Jul 1, 2026
13d4984
Address review nits in Symbol Database DI-active gating
p-ddsign Jul 1, 2026
0f171c2
Sync Symbol Database upload lifecycle with DI enable/disable via RC
p-ddsign Jul 1, 2026
1c2360c
Gate Symbol Database RC advertising on runtime support
p-ddsign Jul 1, 2026
2f40566
Document symbol_database.enabled as tri-state in settings table
p-ddsign Jul 1, 2026
9ba2c45
Merge remote-tracking branch 'origin/master' into revert-5818-claude/…
p-ddsign Jul 1, 2026
5ce1c1d
Stub Symbol Database component in DI implicit enablement spec
p-ddsign Jul 1, 2026
8dd6416
Restart Symbol Database upload after DI disable/re-enable
p-ddsign Jul 1, 2026
27da90c
Build Symbol Database component under force_upload regardless of DI
p-ddsign Jul 1, 2026
7ed163e
Tighten enable_symbol_database? RBS and drop stray blank line
p-ddsign Jul 1, 2026
ebd0a2b
Merge branch 'master' into revert-5818-claude/symdb-default-off
p-datadog Jul 2, 2026
7c3fd10
symbol database: drop write-only @upload_pending state
p-ddsign Jul 3, 2026
38dc4dd
symbol database: derive deferred_by_di_gate? from upload_allowed?
p-ddsign Jul 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions docs/DynamicInstrumentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -343,12 +343,19 @@ names, method names, and method parameters when creating probes.

### Enabling the Symbol Database

Symbol Database upload is disabled by default. To enable it, set:
Symbol Database upload follows Dynamic Instrumentation. By default it
uploads symbols only when Dynamic Instrumentation is actually enabled —
either explicitly (`DD_DYNAMIC_INSTRUMENTATION_ENABLED=true`) or implicitly
when you open the DI UI for your service (which enables Dynamic
Instrumentation via Remote Configuration).

To upload symbols regardless of Dynamic Instrumentation:

export DD_SYMBOL_DATABASE_UPLOAD_ENABLED=true

Once enabled, the upload activates via Remote Configuration when you open
the DI UI for your service.
To explicitly disable it:

export DD_SYMBOL_DATABASE_UPLOAD_ENABLED=false

## Rate Limiting and Performance

Expand Down
6 changes: 3 additions & 3 deletions docs/GettingStarted.md
Original file line number Diff line number Diff line change
Expand Up @@ -2970,15 +2970,15 @@ Alternatively, set DI parameters inside a `Datadog.configure` block:

#### Symbol Database

When Dynamic Instrumentation is enabled, the tracer can extract and upload symbol information (class names, method signatures, parameter names) from your application to enable auto-completion in the DI UI. Symbol Database upload is disabled by default; enable it to allow Remote Configuration to activate uploads.
When Dynamic Instrumentation is enabled, the tracer can extract and upload symbol information (class names, method signatures, parameter names) from your application to enable auto-completion in the DI UI. Symbol Database upload follows Dynamic Instrumentation: by default it uploads symbols only when Dynamic Instrumentation is actually enabled (via `DD_DYNAMIC_INSTRUMENTATION_ENABLED` or implicit enablement through the DI UI), and stays off otherwise. When it uploads, it activates automatically using Remote Configuration. Set `DD_SYMBOL_DATABASE_UPLOAD_ENABLED` (or `c.symbol_database.enabled`) to `true`/`false` to override: `true` uploads regardless of Dynamic Instrumentation, `false` disables it entirely.

| Environment variable | Type | Description | Default |
|---|---|---|---|
| `DD_SYMBOL_DATABASE_UPLOAD_ENABLED` | `Boolean` | Enable or disable symbol database upload. | `false` |
| `DD_SYMBOL_DATABASE_UPLOAD_ENABLED` | `Boolean` | Enable or disable symbol database upload. | Unset: uploads only when Dynamic Instrumentation is actually enabled |

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: For consistency with the c.symbol_database.enabled, should this also say that Unset refers to nil?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so because the env vars and settings are different: the settings are always defined (and thus might have nil as value), but env vars can be not set (in which case referencing ENV['WHATEVER'] would return nil but it's not because WHATEVER is actually in ENV, if it was the value would be the empty string).

The existing text is consistent with the DD_DYNAMIC_INSTRUMENTATION_ENABLED text above which also uses "unset" terminology.


| Setting | Type | Description | Default |
|---|---|---|---|
| `c.symbol_database.enabled` | `Boolean` | Enable or disable symbol database upload. | `false` |
| `c.symbol_database.enabled` | `Boolean, nil` | Enable or disable symbol database upload; `nil` (unset) follows Dynamic Instrumentation. | Unset (`nil`): uploads only when Dynamic Instrumentation is actually enabled |

Symbol Database requires MRI Ruby 2.7+ and Remote Configuration (enabled by default). For details on what is extracted, which code is included, and behavior differences across Ruby versions, see [Dynamic Instrumentation — Symbol Database](DynamicInstrumentation.md#symbol-database).

Expand Down
1 change: 1 addition & 0 deletions lib/datadog.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
require_relative 'datadog/ai_guard'
require_relative 'datadog/appsec'
require_relative 'datadog/di'
require_relative 'datadog/symbol_database/extensions'
require_relative 'datadog/data_streams'
require_relative 'datadog/open_feature'

Expand Down
48 changes: 47 additions & 1 deletion lib/datadog/core/configuration/components.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,38 @@ def build_health_metrics(settings, logger, telemetry)
Core::Diagnostics::Health::Metrics.new(telemetry: telemetry, logger: logger, **options)
end

# Decides whether to build the SymbolDatabase component, for the
# tri-state symbol_database.enabled setting: true/false are explicit
# overrides; nil (the default) mirrors Dynamic Instrumentation by
# building whenever DI's component was built. dynamic_instrumentation
# is DI's build result — nil only when DI is explicitly disabled or the
# runtime can't support it (Rails development mode, missing C
# extension, remote config off, non-MRI). Under the always-build model
# it is non-nil even when the DI setting defaults to off, so a built
# SymbolDatabase component is inert until an upload is actually
# permitted: the component's own gate (see Component#upload_allowed?)
# only extracts and uploads when DI is truly active or the customer
# opted in explicitly. This mirrors DI advertising/building a component
# by default while installing no probes until it is enabled.
# force_upload (internal/testing) always builds, since it uploads
# regardless of DI or the enabled setting.
# @param settings [Configuration::Settings]
# @param dynamic_instrumentation [DI::Component, nil]
# @return [Boolean]
def enable_symbol_database?(settings, dynamic_instrumentation)
# The symbol_database settings group is only registered on the full
# library load path; a partial load (e.g. require 'datadog/di') leaves
# it absent, in which case the feature cannot be enabled.
return false unless settings.respond_to?(:symbol_database)

# force_upload uploads unconditionally, so the component must be built
# even when the setting is nil and DI's component was not built.
return true if settings.symbol_database.internal.force_upload

# nil (the default) follows whether DI's component was built.
Datadog::SymbolDatabase.resolve_enabled(settings.symbol_database.enabled, !dynamic_instrumentation.nil?)
Comment thread
p-datadog marked this conversation as resolved.
Comment thread
p-datadog marked this conversation as resolved.
end
Comment thread
p-datadog marked this conversation as resolved.

def build_logger(settings)
logger = settings.logger.instance || Core::Logger.new($stderr)
logger.level = settings.diagnostics.debug ? ::Logger::DEBUG : settings.logger.level
Expand Down Expand Up @@ -174,7 +206,21 @@ def initialize(settings)
@ai_guard = Datadog::AIGuard::Component.build(settings, logger: @logger, telemetry: telemetry)
@open_feature = OpenFeature::Component.build(settings, agent_settings, logger: @logger, telemetry: telemetry)
@dynamic_instrumentation = Datadog::DI::Component.build(settings, agent_settings, @logger, telemetry: telemetry)
@symbol_database = Datadog::SymbolDatabase::Component.build(settings, agent_settings, @logger, telemetry: telemetry)
# Only build symbol database when enabled, so a disabled component is
# never constructed.
@symbol_database =
if self.class.enable_symbol_database?(settings, @dynamic_instrumentation)
# di_active is a live predicate, not a snapshot: DI may start after
# this component is built (implicit enablement via remote config).
# Symbol Database holds only this opaque proc, never a DI reference,
# so the two modules stay independent — the orchestration layer
# owns the cross-feature knowledge.
Datadog::SymbolDatabase::Component.build(
settings, agent_settings, @logger,
telemetry: telemetry,
di_active: -> { dynamic_instrumentation&.started? || false },
)
end
@error_tracking = Datadog::ErrorTracking::Component.build(settings, @tracer, @logger)
@data_streams = self.class.build_data_streams(settings, agent_settings, @logger, @agent_info)
# Reflects "the customer configured DI to be on" — true iff the
Expand Down
3 changes: 0 additions & 3 deletions lib/datadog/core/configuration/settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

require_relative '../../tracing/configuration/settings'
require_relative '../../opentelemetry/configuration/settings'
require_relative '../../symbol_database/configuration'

module Datadog
module Core
Expand Down Expand Up @@ -1130,8 +1129,6 @@ def initialize(*_)
extend Datadog::Tracing::Configuration::Settings

extend Datadog::OpenTelemetry::Configuration::Settings

extend Datadog::SymbolDatabase::Configuration::Settings
end
# standard:enable Metrics/BlockLength
end
Expand Down
22 changes: 15 additions & 7 deletions lib/datadog/core/remote/client/capabilities.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
require_relative '../../../appsec/remote'
require_relative '../../../tracing/remote'
require_relative '../../../di/remote'
require_relative '../../../symbol_database'
require_relative '../../../symbol_database/remote'
require_relative '../../../open_feature/remote'

Expand Down Expand Up @@ -62,13 +63,20 @@ def register(settings)
end

# Skip symbol database registration on runtimes that cannot run it
# (JRuby, Ruby < 2.7): advertising LIVE_DEBUGGING_SYMBOL_DB there
# would invite symbol-upload configs the component can never serve.
if settings.respond_to?(:symbol_database) && settings.symbol_database.enabled &&
Datadog::SymbolDatabase.supported_runtime?
register_capabilities(Datadog::SymbolDatabase::Remote.capabilities)
register_products(Datadog::SymbolDatabase::Remote.products)
register_receivers(Datadog::SymbolDatabase::Remote.receivers(@telemetry))
# (JRuby, Ruby < 2.7): DI supports Ruby 2.6 but Symbol Database does
# not, so advertising LIVE_DEBUGGING_SYMBOL_DB there would invite
# symbol-upload configs the component can never serve.
if settings.respond_to?(:symbol_database) && Datadog::SymbolDatabase.supported_runtime?
# Symbol database follows DI: when unset it advertises whenever DI
# advertises (mirror the DI branch above, including the unset/default
# case that RC may enable). An explicit symbol_database.enabled wins.
di_enabled = settings.respond_to?(:dynamic_instrumentation) &&
!Datadog::DI::Remote.explicitly_disabled?(settings)
Comment thread
p-datadog marked this conversation as resolved.
if Datadog::SymbolDatabase.resolve_enabled(settings.symbol_database.enabled, di_enabled)
Comment thread
p-datadog marked this conversation as resolved.
register_capabilities(Datadog::SymbolDatabase::Remote.capabilities)
register_products(Datadog::SymbolDatabase::Remote.products)
register_receivers(Datadog::SymbolDatabase::Remote.receivers(@telemetry))
end
end

if settings.respond_to?(:open_feature) && settings.open_feature.enabled
Expand Down
28 changes: 20 additions & 8 deletions lib/datadog/symbol_database.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# frozen_string_literal: true

require_relative 'ruby_version'

module Datadog
# Namespace for Datadog symbol database upload.
#
Expand Down Expand Up @@ -46,14 +48,24 @@ module SymbolDatabase
# @see https://www.postgresql.org/docs/current/datatype-numeric.html
UNKNOWN_MAX_LINE = 2147483647

class << self
# Whether the current Ruby runtime can run symbol database extraction:
# MRI (CRuby) on Ruby 2.7 or later.
#
# @return [Boolean]
def supported_runtime?
RUBY_ENGINE == 'ruby' && RubyVersion.is?('>= 2.7')
end
# Collapses the symbol_database.enabled tri-state setting to a boolean.
# An explicit true/false wins; nil (unconfigured) yields the caller-supplied
# fallback.
# @param setting_value [Boolean, nil] the symbol_database.enabled setting
# @param di_fallback [Boolean] value used when the setting is unconfigured
# @return [Boolean]
def self.resolve_enabled(setting_value, di_fallback)
setting_value.nil? ? di_fallback : setting_value
end

# Whether the current Ruby runtime can run symbol database extraction:
# MRI (CRuby) on Ruby 2.7 or later. Used by the remote-config layer to avoid
# advertising the product on runtimes where Component.build would return nil
# (e.g. Ruby 2.6, which Dynamic Instrumentation supports but Symbol Database
# does not).
# @return [Boolean]
def self.supported_runtime?
RUBY_ENGINE == 'ruby' && RubyVersion.is?('>= 2.7')
end
end
end
Loading
Loading