Skip to content

Commit

Permalink
DEBUG-3182 DI railtie (#4272)
Browse files Browse the repository at this point in the history
  • Loading branch information
p-datadog authored Jan 14, 2025
1 parent 8f97fe7 commit 5361e8e
Show file tree
Hide file tree
Showing 30 changed files with 310 additions and 42 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
10 changes: 1 addition & 9 deletions integration/apps/hanami/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,7 @@ gem 'unicorn'
gem 'webrick'
gem 'pry-byebug'

gem_spec = Datadog::DemoEnv.gem_spec('datadog')
req = {require: 'datadog/auto_instrument'}
opts = if gem_spec.last.is_a?(Hash)
gem_spec.pop.merge(req)
else
req
end
gem_spec << opts
gem 'datadog', *gem_spec
gem *Datadog::DemoEnv.gem_datadog_auto_instrument
gem 'google-protobuf', '~> 3.0'

group :development do
Expand Down
2 changes: 1 addition & 1 deletion integration/apps/rails-five/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ gem 'unicorn'
gem 'loofah', '2.19.1'

# Choose correct specs for 'datadog' demo environment
gem 'datadog', *Datadog::DemoEnv.gem_spec('datadog')
gem *Datadog::DemoEnv.gem_datadog_auto_instrument

gem 'dogstatsd-ruby'
gem 'ffi'
Expand Down
6 changes: 6 additions & 0 deletions integration/apps/rails-five/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
8 changes: 4 additions & 4 deletions integration/apps/rails-five/bin/run
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ puts "\n== Starting application process =="
process = (ARGV[0] || Datadog::DemoEnv.process)
command = case process
when 'puma'
"bundle exec ddprofrb exec puma -C /app/config/puma.rb"
"bundle exec puma -C /app/config/puma.rb"
when 'unicorn'
"bundle exec ddprofrb exec unicorn -c /app/config/unicorn.rb"
"bundle exec unicorn -c /app/config/unicorn.rb"
when 'console'
"bundle exec ddprofrb exec rails c"
"bundle exec rails c"
when 'irb'
"bundle exec ddprofrb exec irb"
"bundle exec irb"
when nil, ''
abort("\n== ERROR: Must specify a application process! ==")
else
Expand Down
6 changes: 6 additions & 0 deletions integration/apps/rails-five/config/initializers/datadog.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,10 @@
c.profiling.exporter.transport = Datadog::DemoEnv.profiler_file_transport
end
end

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

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

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

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

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

it 'is loaded' do
expect(response.code).to eq '200'

# 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"=>"Time", "value"=>String}],
[{"type"=>"String", "value"=>"updated_at"},
{"type"=>"Time", "value"=>String}]]}],
[{"type"=>"Symbol", "value"=>"new_record"}, {"type"=>"FalseClass", "value"=>"false"}]]}
)
end
end
end
19 changes: 19 additions & 0 deletions integration/apps/rails-five/spec/support/integration_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,23 @@ def get(path)
Net::HTTP.get_response(uri)
end
end

module ClassMethods
def di_test
if RUBY_ENGINE == 'jruby'
before(:all) do
skip "Dynamic instrumentation is not supported on JRuby"
end
end
if RUBY_VERSION < "2.6"
before(:all) do
skip "Dynamic instrumentation requires Ruby 2.6 or higher"
end
end
end
end

def self.included(base)
base.extend(ClassMethods)
end
end
2 changes: 1 addition & 1 deletion integration/apps/rails-seven/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gem "rails", "~> 7.0.5"

# Choose correct specs for 'datadog' demo environment
gem 'datadog', *Datadog::DemoEnv.gem_spec('datadog')
gem *Datadog::DemoEnv.gem_datadog_auto_instrument

gem 'dogstatsd-ruby'

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
8 changes: 4 additions & 4 deletions integration/apps/rails-seven/bin/run
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ puts "\n== Starting application process =="
process = (ARGV[0] || Datadog::DemoEnv.process)
command = case process
when 'puma'
"bundle exec ddprofrb exec puma -C /app/config/puma.rb"
"bundle exec puma -C /app/config/puma.rb"
when 'unicorn'
"bundle exec ddprofrb exec unicorn -c /app/config/unicorn.rb"
"bundle exec unicorn -c /app/config/unicorn.rb"
when 'console'
"bundle exec ddprofrb exec rails c"
"bundle exec rails c"
when 'irb'
"bundle exec ddprofrb exec irb"
"bundle exec irb"
when nil, ''
abort("\n== ERROR: Must specify a application process! ==")
else
Expand Down
7 changes: 6 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,10 @@
# Reconfigure transport to write pprof to file
c.profiling.exporter.transport = Datadog::DemoEnv.profiler_file_transport
end

if c.respond_to?(:dynamic_instrumentation)
c.remote.enabled = true
c.dynamic_instrumentation.enabled = true
c.dynamic_instrumentation.internal.development = true
end
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
36 changes: 36 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,36 @@
require 'spec_helper'
require 'json'

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

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

it 'is loaded' do
expect(response.code).to eq '200'

# 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: 19 additions & 0 deletions integration/apps/rails-seven/spec/support/integration_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,23 @@ def get(path)
Net::HTTP.get_response(uri)
end
end

module ClassMethods
def di_test
if RUBY_ENGINE == 'jruby'
before(:all) do
skip "Dynamic instrumentation is not supported on JRuby"
end
end
if RUBY_VERSION < "2.6"
before(:all) do
skip "Dynamic instrumentation requires Ruby 2.6 or higher"
end
end
end
end

def self.included(base)
base.extend(ClassMethods)
end
end
11 changes: 9 additions & 2 deletions integration/apps/rails-six/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ gem 'puma'
gem 'unicorn'

# Choose correct specs for 'datadog' demo environment
gem 'datadog', *Datadog::DemoEnv.gem_spec('datadog')
gem *Datadog::DemoEnv.gem_datadog_auto_instrument

gem 'dogstatsd-ruby'
gem 'ffi'
Expand Down Expand Up @@ -90,7 +90,14 @@ end

group :test, :development do
gem 'byebug', platform: :ruby
gem 'mock_redis'
# mock_redis 0.47.0+ requires redis 5 or higher
# mock_redis 0.42.0+ requires Ruby 3.0 or higher
# mock_redis 0.37.0+ requires Ruby 2.7 or higher
if RUBY_VERSION >= '2.7'
gem 'mock_redis', '~> 0.37.0'
else
gem 'mock_redis', '< 0.37.0'
end
gem 'parallel_tests'

gem 'listen'
Expand Down
6 changes: 6 additions & 0 deletions integration/apps/rails-six/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
8 changes: 4 additions & 4 deletions integration/apps/rails-six/bin/run
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ puts "\n== Starting application process =="
process = (ARGV[0] || Datadog::DemoEnv.process)
command = case process
when 'puma'
"bundle exec ddprofrb exec puma -C /app/config/puma.rb"
"bundle exec puma -C /app/config/puma.rb"
when 'unicorn'
"bundle exec ddprofrb exec unicorn -c /app/config/unicorn.rb"
"bundle exec unicorn -c /app/config/unicorn.rb"
when 'console'
"bundle exec ddprofrb exec rails c"
"bundle exec rails c"
when 'irb'
"bundle exec ddprofrb exec irb"
"bundle exec irb"
when nil, ''
abort("\n== ERROR: Must specify a application process! ==")
else
Expand Down
6 changes: 6 additions & 0 deletions integration/apps/rails-six/config/initializers/datadog.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,10 @@
c.profiling.exporter.transport = Datadog::DemoEnv.profiler_file_transport
end
end

if c.respond_to?(:dynamic_instrumentation)
c.remote.enabled = true
c.dynamic_instrumentation.enabled = true
c.dynamic_instrumentation.internal.development = true
end
end
2 changes: 2 additions & 0 deletions integration/apps/rails-six/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
36 changes: 36 additions & 0 deletions integration/apps/rails-six/spec/integration/di_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
require 'spec_helper'
require 'json'

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

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

it 'is loaded' do
expect(response.code).to eq '200'

# 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"=>"Time", "value"=>String}],
[{"type"=>"String", "value"=>"updated_at"},
{"type"=>"Time", "value"=>String}]]}],
[{"type"=>"Symbol", "value"=>"new_record"}, {"type"=>"FalseClass", "value"=>"false"}]]}
)
end
end
end
19 changes: 19 additions & 0 deletions integration/apps/rails-six/spec/support/integration_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,23 @@ def get(path)
Net::HTTP.get_response(uri)
end
end

module ClassMethods
def di_test
if RUBY_ENGINE == 'jruby'
before(:all) do
skip "Dynamic instrumentation is not supported on JRuby"
end
end
if RUBY_VERSION < "2.6"
before(:all) do
skip "Dynamic instrumentation requires Ruby 2.6 or higher"
end
end
end
end

def self.included(base)
base.extend(ClassMethods)
end
end
Loading

0 comments on commit 5361e8e

Please sign in to comment.