Skip to content

Commit

Permalink
- Added mocked agent and force trace formatting to test Datadog-Clien…
Browse files Browse the repository at this point in the history
…t-Computed-Stats header and _sampling_priority_v1 tag

- Reproduced system-tests ASM Standalone tests
  • Loading branch information
vpellan committed Oct 7, 2024
1 parent 632eb8d commit 1091dd3
Show file tree
Hide file tree
Showing 4 changed files with 440 additions and 68 deletions.
97 changes: 67 additions & 30 deletions spec/datadog/appsec/contrib/rack/integration_test_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,34 @@
RSpec.describe 'Rack integration tests' do
include Rack::Test::Methods

# We send the trace to a mocked agent to verify that the trace includes the headers that we want
# In the future, it might be a good idea to use the traces that the mocked agent
# receives in the tests/shared examples
let(:agent_http_client) do
Datadog::Tracing::Transport::HTTP.default do |t|
t.adapter agent_http_adapter
end
end

let(:agent_http_adapter) { Datadog::Core::Transport::HTTP::Adapters::Net.new(agent_settings) }

let(:agent_settings) do
Datadog::Core::Configuration::AgentSettingsResolver::AgentSettings.new(
adapter: nil,
ssl: false,
uds_path: nil,
hostname: 'localhost',
port: 6218,
timeout_seconds: 30,
)
end

let(:agent_tested_headers) { {} }

let(:tracing_enabled) { true }
let(:appsec_enabled) { true }

let(:appsec_standalone_enabled) { false }
let(:tracing_enabled) { true }
let(:remote_enabled) { false }
let(:appsec_ip_passlist) { [] }
let(:appsec_ip_denylist) { [] }
Expand Down Expand Up @@ -142,6 +167,22 @@
}
end

# Mocked agent with correct headers
stub_request(:post, 'http://localhost:6218/v0.4/traces')
.with do |request|
agent_tested_headers <= request.headers
end
.to_return(status: 200)

# DEV: Would it be faster to do another stub for requests that don't match the headers
# rather than waiting for the TCP connection to fail?

# TODO: Mocked agent that matches a given body, then use it in the shared examples,
# That way it would be real integration tests

# We must format the trace to have the same result as the agent
# This is especially important for _sampling_priority_v1 metric

unless remote_enabled
Datadog.configure do |c|
c.tracing.enabled = tracing_enabled
Expand Down Expand Up @@ -205,11 +246,12 @@
let(:client_ip) { remote_addr }

let(:service_span) do
span = spans.find { |s| s.metrics.fetch('_dd.top_level', -1.0) > 0.0 }

expect(span.name).to eq 'rack.request'
spans.find { |s| s.metrics.fetch('_dd.top_level', -1.0) > 0.0 }
end

span
let(:span) do
Datadog::Tracing::Transport::TraceFormatter.format!(trace)
spans.find { |s| s.name == 'rack.request' }
end

context 'with remote configuration' do
Expand Down Expand Up @@ -243,24 +285,6 @@
map '/success/' do
run(proc { |_env| [200, { 'Content-Type' => 'text/html' }, ['OK']] })
end

map '/requestdownstream' do
run(
proc do |_env|
uri = URI('http://localhost:3000/returnheaders')
ext_request = nil
ext_response = nil

Net::HTTP.start(uri.host, uri.port) do |http|
ext_request = Net::HTTP::Get.new(uri)

ext_response = http.request(ext_request)
end

[200, { 'Content-Type' => 'application/json' }, [ext_response.body]]
end
)
end
end
end

Expand Down Expand Up @@ -626,6 +650,24 @@
end
)
end

map '/requestdownstream' do
run(
proc do |_env|
uri = URI('http://localhost:3000/returnheaders')
ext_request = nil
ext_response = nil

Net::HTTP.start(uri.host, uri.port) do |http|
ext_request = Net::HTTP::Get.new(uri)

ext_response = http.request(ext_request)
end

[200, { 'Content-Type' => 'application/json' }, [ext_response.body]]
end
)
end
end
end

Expand Down Expand Up @@ -851,13 +893,6 @@
it_behaves_like 'a trace with AppSec api security tags'
end
end

context 'with APM disabled' do
let(:appsec_standalone_enabled) { true }

it_behaves_like 'normal with tracing disable'
it_behaves_like 'a trace with ASM Standalone tags'
end
end

describe 'POST request' do
Expand Down Expand Up @@ -987,6 +1022,8 @@
end
end
end

it_behaves_like 'appsec standalone billing'
end
end
end
62 changes: 48 additions & 14 deletions spec/datadog/appsec/contrib/rails/integration_test_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,33 @@
RSpec.describe 'Rails integration tests' do
include Rack::Test::Methods

# We send the trace to a mocked agent to verify that the trace includes the headers that we want
# In the future, it might be a good idea to use the traces that the mocked agent
# receives in the tests/shared examples
let(:agent_http_client) do
Datadog::Tracing::Transport::HTTP.default do |t|
t.adapter agent_http_adapter
end
end

let(:agent_http_adapter) { Datadog::Core::Transport::HTTP::Adapters::Net.new(agent_settings) }

let(:agent_settings) do
Datadog::Core::Configuration::AgentSettingsResolver::AgentSettings.new(
adapter: nil,
ssl: false,
uds_path: nil,
hostname: 'localhost',
port: 6218,
timeout_seconds: 30,
)
end

let(:sorted_spans) do
# We must format the trace to have the same result as the agent
# This is especially important for _sampling_priority_v1 metric
Datadog::Tracing::Transport::TraceFormatter.format!(trace)

chain = lambda do |start|
loop.with_object([start]) do |_, o|
# root reached (default)
Expand All @@ -27,15 +53,19 @@
sort.call(spans)
end

let(:agent_tested_headers) { {} }

let(:rack_span) { sorted_spans.reverse.find { |x| x.name == Datadog::Tracing::Contrib::Rack::Ext::SPAN_REQUEST } }

let(:tracing_enabled) { true }
let(:appsec_enabled) { true }

let(:appsec_instrument_rack) { false }

let(:appsec_standalone_enabled) { false }
let(:tracing_enabled) { true }
let(:appsec_ip_denylist) { [] }
let(:appsec_user_id_denylist) { [] }
let(:appsec_ruleset) { :recommended }
let(:appsec_instrument_rack) { false }
let(:api_security_enabled) { false }
let(:api_security_sample) { 0.0 }

Expand Down Expand Up @@ -100,6 +130,19 @@
}
end

# Mocked agent with correct headers
stub_request(:post, 'http://localhost:6218/v0.4/traces')
.with do |request|
agent_tested_headers <= request.headers
end
.to_return(status: 200)

# DEV: Would it be faster to do another stub for requests that don't match the headers
# rather than waiting for the TCP connection to fail?

# TODO: Mocked agent that matches a given body, then use it in the shared examples,
# That way it would be real integration tests

Datadog.configure do |c|
c.tracing.enabled = tracing_enabled

Expand Down Expand Up @@ -185,11 +228,7 @@ def request_downstream
let(:client_ip) { remote_addr }

let(:service_span) do
span = sorted_spans.reverse.find { |s| s.metrics.fetch('_dd.top_level', -1.0) > 0.0 }

expect(span.name).to eq 'rack.request'

span
sorted_spans.reverse.find { |s| s.metrics.fetch('_dd.top_level', -1.0) > 0.0 }
end

let(:span) { rack_span }
Expand Down Expand Up @@ -343,13 +382,6 @@ def request_downstream
it_behaves_like 'a trace with AppSec api security tags'
end
end

context 'with APM disabled' do
let(:appsec_standalone_enabled) { true }

it_behaves_like 'normal with tracing disable'
it_behaves_like 'a trace with ASM Standalone tags'
end
end

describe 'POST request' do
Expand Down Expand Up @@ -525,6 +557,8 @@ def request_downstream
end
end
end

it_behaves_like 'appsec standalone billing'
end
end
end
59 changes: 46 additions & 13 deletions spec/datadog/appsec/contrib/sinatra/integration_test_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,33 @@
RSpec.describe 'Sinatra integration tests' do
include Rack::Test::Methods

# We send the trace to a mocked agent to verify that the trace includes the headers that we want
# In the future, it might be a good idea to use the traces that the mocked agent
# receives in the tests/shared examples
let(:agent_http_client) do
Datadog::Tracing::Transport::HTTP.default do |t|
t.adapter agent_http_adapter
end
end

let(:agent_http_adapter) { Datadog::Core::Transport::HTTP::Adapters::Net.new(agent_settings) }

let(:agent_settings) do
Datadog::Core::Configuration::AgentSettingsResolver::AgentSettings.new(
adapter: nil,
ssl: false,
uds_path: nil,
hostname: 'localhost',
port: 6218,
timeout_seconds: 30,
)
end

let(:sorted_spans) do
# We must format the trace to have the same result as the agent
# This is especially important for _sampling_priority_v1 metric
Datadog::Tracing::Transport::TraceFormatter.format!(trace)

chain = lambda do |start|
loop.with_object([start]) do |_, o|
# root reached (default)
Expand All @@ -37,13 +63,16 @@
sort.call(spans)
end

let(:agent_tested_headers) { {} }

let(:sinatra_span) { sorted_spans.reverse.find { |x| x.name == Datadog::Tracing::Contrib::Sinatra::Ext::SPAN_REQUEST } }
let(:route_span) { sorted_spans.find { |x| x.name == Datadog::Tracing::Contrib::Sinatra::Ext::SPAN_ROUTE } }
let(:rack_span) { sorted_spans.reverse.find { |x| x.name == Datadog::Tracing::Contrib::Rack::Ext::SPAN_REQUEST } }

let(:tracing_enabled) { true }
let(:appsec_enabled) { true }

let(:appsec_standalone_enabled) { false }
let(:tracing_enabled) { true }
let(:appsec_ip_denylist) { [] }
let(:appsec_user_id_denylist) { [] }
let(:appsec_ruleset) { :recommended }
Expand Down Expand Up @@ -108,6 +137,19 @@
}
end

# Mocked agent with correct headers
stub_request(:post, 'http://localhost:6218/v0.4/traces')
.with do |request|
agent_tested_headers <= request.headers
end
.to_return(status: 200)

# DEV: Would it be faster to do another stub for requests that don't match the headers
# rather than waiting for the TCP connection to fail?

# TODO: Mocked agent that matches a given body, then use it in the shared examples,
# That way it would be real integration tests

Datadog.configure do |c|
c.tracing.enabled = tracing_enabled

Expand Down Expand Up @@ -163,11 +205,7 @@
let(:client_ip) { remote_addr }

let(:service_span) do
span = sorted_spans.reverse.find { |s| s.metrics.fetch('_dd.top_level', -1.0) > 0.0 }

expect(span.name).to eq 'rack.request'

span
sorted_spans.reverse.find { |s| s.metrics.fetch('_dd.top_level', -1.0) > 0.0 }
end

let(:span) { rack_span }
Expand Down Expand Up @@ -347,13 +385,6 @@
it_behaves_like 'a trace with AppSec api security tags'
end
end

context 'with APM disabled' do
let(:appsec_standalone_enabled) { true }

it_behaves_like 'normal with tracing disable'
it_behaves_like 'a trace with ASM Standalone tags'
end
end

describe 'POST request' do
Expand Down Expand Up @@ -441,6 +472,8 @@
it_behaves_like 'a trace with AppSec api security tags'
end
end

it_behaves_like 'appsec standalone billing'
end
end
end
Loading

0 comments on commit 1091dd3

Please sign in to comment.