Skip to content

Commit

Permalink
DI railtie
Browse files Browse the repository at this point in the history
  • Loading branch information
p committed Jan 9, 2025
1 parent aff0f7c commit 6eea862
Show file tree
Hide file tree
Showing 10 changed files with 104 additions and 16 deletions.
1 change: 1 addition & 0 deletions Steepfile
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ target :datadog do
ignore 'lib/datadog/core/workers/queue.rb'
ignore 'lib/datadog/core/workers/runtime_metrics.rb'
ignore 'lib/datadog/di/configuration/settings.rb'
ignore 'lib/datadog/di/contrib/railtie.rb'
ignore 'lib/datadog/kit/appsec/events.rb' # disabled because of https://github.com/soutaro/steep/issues/701
ignore 'lib/datadog/kit/identity.rb' # disabled because of https://github.com/soutaro/steep/issues/701
ignore 'lib/datadog/opentelemetry.rb'
Expand Down
6 changes: 6 additions & 0 deletions integration/apps/rails-seven/app/controllers/di_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class DiController < ApplicationController
def ar_serializer
test = Test.create!
render json: Datadog::DI.component.serializer.serialize_value(test)
end
end
5 changes: 4 additions & 1 deletion integration/apps/rails-seven/config/initializers/datadog.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
require 'datadog/statsd'
require 'datadog'
require 'datadog/appsec'

Datadog.configure do |c|
c.env = 'integration'
Expand All @@ -26,4 +25,8 @@
# Reconfigure transport to write pprof to file
c.profiling.exporter.transport = Datadog::DemoEnv.profiler_file_transport
end

c.remote.enabled = true
c.dynamic_instrumentation.enabled = true
c.dynamic_instrumentation.internal.development = true
end
2 changes: 2 additions & 0 deletions integration/apps/rails-seven/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
get 'basic/fibonacci', to: 'basic#fibonacci'
get 'basic/boom', to: 'basic#boom'

get 'di/ar_serializer', to: 'di#ar_serializer'

# Job test scenarios
post 'jobs', to: 'jobs#create'
end
32 changes: 32 additions & 0 deletions integration/apps/rails-seven/spec/integration/di_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require 'spec_helper'
require 'json'

RSpec.describe 'Dynamic Instrumentation' do
include_context 'integration test'

describe 'ActiveRecord integration' do
subject { JSON.parse(get('di/ar_serializer').body) }

it 'is loaded' do
# If AR integration is loaded, this output will be the result of
# the custom serializer.
# If AR integration is not loaded, the output here will have a bunch of
# internal AR fields but not the attributes themselves.
expect(subject).to match(
{"type"=>"Test",
"entries"=>
[[{"type"=>"Symbol", "value"=>"attributes"},
{"type"=>"Hash",
"entries"=>
[[{"type"=>"String", "value"=>"id"}, {"type"=>"Integer", "value"=>String}],
[{"type"=>"String", "value"=>"version"}, {"type"=>"NilClass", "isNull"=>true}],
[{"type"=>"String", "value"=>"data"}, {"type"=>"NilClass", "isNull"=>true}],
[{"type"=>"String", "value"=>"created_at"},
{"type"=>"ActiveSupport::TimeWithZone", "value"=>String}],
[{"type"=>"String", "value"=>"updated_at"},
{"type"=>"ActiveSupport::TimeWithZone", "value"=>String}]]}],
[{"type"=>"Symbol", "value"=>"new_record"}, {"type"=>"FalseClass", "value"=>"false"}]]}
)
end
end
end
19 changes: 4 additions & 15 deletions lib/datadog/di.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,6 @@
require_relative 'di/transport'
require_relative 'di/utils'

if defined?(ActiveRecord::Base)
# The third-party library integrations need to be loaded after the
# third-party libraries are loaded. Tracing and appsec use Railtie
# to delay integrations until all of the application's dependencies
# are loaded, when running under Rails. We should do the same here in
# principle, however DI currently only has an ActiveRecord integration
# and AR should be loaded before any application code is loaded, being
# part of Rails, therefore for now we should be OK to just require the
# AR integration from here.
#
# TODO this require might need to be delayed via Rails post-initialization
# logic?
require_relative 'di/contrib/active_record'
end

module Datadog
# Namespace for Datadog dynamic instrumentation.
#
Expand Down Expand Up @@ -75,3 +60,7 @@ def component
# for line probes to work) activate tracking in an initializer.
Datadog::DI.activate_tracking
end

require_relative 'di/contrib'

Datadog::DI::Contrib.load_now_or_later
23 changes: 23 additions & 0 deletions lib/datadog/di/contrib.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: true

require_relative '../core/contrib/rails/utils'

module Datadog
module DI
module Contrib
module_function def load_now_or_later
if Datadog::Core::Contrib::Rails::Utils.railtie_supported?
require_relative 'contrib/railtie'
else
load_now
end
end

module_function def load_now
if defined?(ActiveRecord::Base)
require_relative 'contrib/active_record'
end
end
end
end
end
15 changes: 15 additions & 0 deletions lib/datadog/di/contrib/railtie.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

module Datadog
module DI
module Contrib
# Railtie class initializes dynamic instrumentation contrib code
# in Rails environments.
class Railtie < Rails::Railtie
initializer 'datadog.dynamic_instrumentation.initialize' do |app|
Contrib.load_now
end
end
end
end
end
9 changes: 9 additions & 0 deletions sig/datadog/di/contrib.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module Datadog
module DI
module Contrib
def self?.load_now_or_later: () -> void

def self?.load_now: () -> void
end
end
end
8 changes: 8 additions & 0 deletions sig/datadog/di/contrib/railtie.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module Datadog
module DI
module Contrib
class Railtie < Rails::Railtie
end
end
end
end

0 comments on commit 6eea862

Please sign in to comment.