Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
cdb503c
initial commit
wconti27 Aug 7, 2025
0cfc609
change
wconti27 Aug 8, 2025
abdde8e
initial commit
wconti27 Aug 8, 2025
14a87da
Merge branch 'master' into conti/refactor-web-integrations
wconti27 Aug 8, 2025
2592ffb
changes
wconti27 Aug 8, 2025
079a03d
more changes
wconti27 Aug 8, 2025
967d42e
more changes
wconti27 Aug 11, 2025
5e95e7c
more fixes
wconti27 Aug 11, 2025
2f21f3d
merge
wconti27 Aug 11, 2025
e62354f
more changes
wconti27 Aug 11, 2025
be5aa10
another change
wconti27 Aug 11, 2025
897b086
more changes
wconti27 Aug 11, 2025
a502928
more fixes
wconti27 Aug 11, 2025
80953de
fix next
wconti27 Aug 12, 2025
ffeba31
fix http
wconti27 Aug 12, 2025
1384fdc
more fixes
wconti27 Aug 12, 2025
7aefa14
more fixes
wconti27 Aug 12, 2025
76bcb7f
fix azure functions
wconti27 Aug 12, 2025
ff46aab
another fix
wconti27 Aug 12, 2025
64f2a00
fix
wconti27 Aug 12, 2025
18ce9e9
fix supported configurations
wconti27 Aug 12, 2025
d12cf90
fix type
wconti27 Aug 12, 2025
74e4ced
fix supported configs
wconti27 Aug 12, 2025
ce4c4cf
fix lint
wconti27 Aug 12, 2025
b915d97
refactor again
wconti27 Aug 12, 2025
b396139
more fixes
wconti27 Aug 12, 2025
ee613d8
more fixes
wconti27 Aug 12, 2025
5f99e68
fix other appsec failure
wconti27 Aug 12, 2025
1399cc2
use specific system tests branch
wconti27 Aug 12, 2025
936d94a
use correct branch
wconti27 Aug 12, 2025
767abb3
Merge branch 'master' into conti/refactor-web-integrations
wconti27 Aug 13, 2025
402586a
Merge branch 'master' into conti/refactor-web-integrations
wconti27 Aug 18, 2025
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
86 changes: 47 additions & 39 deletions .github/workflows/serverless.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ jobs:
localstack-legacy:
image: localstack/localstack:1.1.0
ports:
- "127.0.0.1:4567:4567" # Edge
- '127.0.0.1:4567:4567' # Edge
env:
LOCALSTACK_SERVICES: dynamodb,kinesis,s3,sqs,sns,redshift,route53,logs,serverless
EXTRA_CORS_ALLOWED_HEADERS: x-amz-request-id,x-amzn-requestid,x-amz-id-2
Expand Down Expand Up @@ -88,31 +88,39 @@ jobs:
suffix: plugins-${{ github.job }}-${{ matrix.node-version }}
- uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3

aws-apigateway:
runs-on: ubuntu-latest
env:
PLUGINS: aws-apigateway
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: ./.github/actions/plugins/test-and-upstream

azure-functions:
runs-on: ubuntu-latest
services:
azurite:
image: mcr.microsoft.com/azure-storage/azurite:3.34.0
ports:
- "127.0.0.1:10000:10000"
- "127.0.0.1:10001:10001"
- "127.0.0.1:10002:10002"
azureservicebusemulator:
image: mcr.microsoft.com/azure-messaging/servicebus-emulator:1.1.2
ports:
- "127.0.0.1:5672:5672"
- "127.0.0.1:5300:5300"
env:
ACCEPT_EULA: "Y"
MSSQL_SA_PASSWORD: "Localtestpass1!"
SQL_SERVER: azuresqledge
azuresqledge:
image: mcr.microsoft.com/azure-sql-edge:1.0.7
ports:
- "127.0.0.1:1433:1433"
env:
ACCEPT_EULA: "Y"
MSSQL_SA_PASSWORD: "Localtestpass1!"
azurite:
image: mcr.microsoft.com/azure-storage/azurite:3.34.0
ports:
- '127.0.0.1:10000:10000'
- '127.0.0.1:10001:10001'
- '127.0.0.1:10002:10002'
azureservicebusemulator:
image: mcr.microsoft.com/azure-messaging/servicebus-emulator:1.1.2
ports:
- '127.0.0.1:5672:5672'
- '127.0.0.1:5300:5300'
env:
ACCEPT_EULA: 'Y'
MSSQL_SA_PASSWORD: 'Localtestpass1!'
SQL_SERVER: azuresqledge
azuresqledge:
image: mcr.microsoft.com/azure-sql-edge:1.0.7
ports:
- '127.0.0.1:1433:1433'
env:
ACCEPT_EULA: 'Y'
MSSQL_SA_PASSWORD: 'Localtestpass1!'
env:
PLUGINS: azure-functions
SERVICES: azureservicebusemulator,azuresqledge
Expand All @@ -127,22 +135,22 @@ jobs:
azure-service-bus:
runs-on: ubuntu-latest
services:
azureservicebusemulator:
image: mcr.microsoft.com/azure-messaging/servicebus-emulator:1.1.2
ports:
- "127.0.0.1:5672:5672"
- "127.0.0.1:5300:5300"
env:
ACCEPT_EULA: "Y"
MSSQL_SA_PASSWORD: "Localtestpass1!"
SQL_SERVER: azuresqledge
azuresqledge:
image: mcr.microsoft.com/azure-sql-edge:1.0.7
ports:
- "127.0.0.1:1433:1433"
env:
ACCEPT_EULA: "Y"
MSSQL_SA_PASSWORD: "Localtestpass1!"
azureservicebusemulator:
image: mcr.microsoft.com/azure-messaging/servicebus-emulator:1.1.2
ports:
- '127.0.0.1:5672:5672'
- '127.0.0.1:5300:5300'
env:
ACCEPT_EULA: 'Y'
MSSQL_SA_PASSWORD: 'Localtestpass1!'
SQL_SERVER: azuresqledge
azuresqledge:
image: mcr.microsoft.com/azure-sql-edge:1.0.7
ports:
- '127.0.0.1:1433:1433'
env:
ACCEPT_EULA: 'Y'
MSSQL_SA_PASSWORD: 'Localtestpass1!'
env:
PLUGINS: azure-service-bus
SERVICES: azureservicebusemulator,azuresqledge
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/system-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,11 @@ jobs:
id-token: write
packages: write
with:
ref: conti/fix-js-web-err
library: nodejs
binaries_artifact: system_tests_binaries
desired_execution_time: 300 # 5 minutes
desired_execution_time: 300 # 5 minutes
scenarios_groups: tracer-release
excluded_scenarios: APM_TRACING_E2E_OTEL,APM_TRACING_E2E_SINGLE_SPAN # require AWS and datadog credentials
excluded_scenarios: APM_TRACING_E2E_OTEL,APM_TRACING_E2E_SINGLE_SPAN # require AWS and datadog credentials
parametric_job_count: 8
skip_empty_scenarios: true
2 changes: 1 addition & 1 deletion packages/datadog-instrumentations/src/hapi.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ function onPreResponse (request, h) {
const req = request.raw.req

if (request.response instanceof Error) {
errorChannel.publish(request.response)
errorChannel.publish({ req, error: request.response })
}

if (request.route) {
Expand Down
9 changes: 9 additions & 0 deletions packages/datadog-plugin-aws-apigateway/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
'use strict'

const InferredProxyPlugin = require('../../datadog-plugin-inferred-proxy/src')

class ApiGatewayPlugin extends InferredProxyPlugin {
static id = 'aws-apigateway'
}

module.exports = ApiGatewayPlugin
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
'use strict'

require('../../setup/tap')

const agent = require('../agent')
const agent = require('../../dd-trace/test/plugins/agent')
const { expect } = require('chai')
const axios = require('axios')
const { Agent } = require('http')
Expand All @@ -13,62 +11,22 @@ const httpClient = axios.create({
timeout: 5000
})

describe('Inferred Proxy Spans', function () {
describe('Plugin', function () {
let http
let appListener
let controller
let port

// tap was throwing timeout errors when trying to use hooks like `before`, so instead we just use this function
// and call before the test starts
const loadTest = async function ({ inferredProxyServicesEnabled = true } = {}) {
const options = {
inferredProxyServicesEnabled,
service: 'aws-server'
}

await agent.load(
['http', 'dns', 'net'],
[{ client: false }, { enabled: false }, { enabled: false }],
options
)

// we can't force re-init the tracer, so we have to set the config manually
const tracer = require('../../../../dd-trace').init(options)
tracer._tracer._config.inferredProxyServicesEnabled = inferredProxyServicesEnabled

http = require('http')

const server = new http.Server(async (req, res) => {
controller && await controller(req, res)
if (req.url === '/error') {
res.statusCode = 500
res.end(JSON.stringify({ message: 'ERROR' }))
} else {
res.writeHead(200)
res.end(JSON.stringify({ message: 'OK' }))
}
})

// Force close connections when server closes
const connections = new Set()
server.on('connection', (connection) => {
connections.add(connection)
connection.on('close', () => {
connections.delete(connection)
})
})

return new Promise((resolve, reject) => {
appListener = server.listen(0, '127.0.0.1', () => {
port = server.address().port
appListener._connections = connections
resolve()
})
})
const inferredHeaders = {
'x-dd-proxy': 'aws-apigateway',
'x-dd-proxy-request-time-ms': '1729780025473',
'x-dd-proxy-path': '/test',
'x-dd-proxy-httpmethod': 'GET',
'x-dd-proxy-domain-name': 'example.com',
'x-dd-proxy-stage': 'dev'
}

const cleanupTest = async function () {
afterEach(async () => {
controller = null

if (appListener) {
Expand All @@ -92,25 +50,54 @@ describe('Inferred Proxy Spans', function () {
}

await agent.close()
}

const inferredHeaders = {
'x-dd-proxy': 'aws-apigateway',
'x-dd-proxy-request-time-ms': '1729780025473',
'x-dd-proxy-path': '/test',
'x-dd-proxy-httpmethod': 'GET',
'x-dd-proxy-domain-name': 'example.com',
'x-dd-proxy-stage': 'dev'
}

afterEach(async () => {
await cleanupTest()
})

describe('without configuration', () => {
it('should create a parent span and a child span for a 200', async () => {
await loadTest({})
beforeEach(async () => {
const options = {
inferredProxyServicesEnabled: true,
service: 'aws-server'
}

await agent.load(
['http', 'dns', 'net', 'tcp', 'aws-apigateway'],
[{ client: false }, { enabled: false }, { enabled: false }, { enabled: false }, { enabled: true }],
options
)

require('../../dd-trace').init(options)
http = require('http')

const server = new http.Server(async (req, res) => {
controller && await controller(req, res)
if (req.url === '/error') {
res.statusCode = 500
res.end(JSON.stringify({ message: 'ERROR' }))
} else {
res.writeHead(200)
res.end(JSON.stringify({ message: 'OK' }))
}
})

// Force close connections when server closes
const connections = new Set()
server.on('connection', (connection) => {
connections.add(connection)
connection.on('close', () => {
connections.delete(connection)
})
})

return new Promise((resolve, reject) => {
appListener = server.listen(0, '127.0.0.1', () => {
port = server.address().port
appListener._connections = connections
resolve()
})
})
})

it('should create a parent span and a child span for a 200', async () => {
await httpClient.get(`http://127.0.0.1:${port}/`, {
headers: inferredHeaders
})
Expand Down Expand Up @@ -148,8 +135,6 @@ describe('Inferred Proxy Spans', function () {
})

it('should create a parent span and a child span for an error', async () => {
await loadTest({})

await httpClient.get(`http://127.0.0.1:${port}/error`, {
headers: inferredHeaders,
validateStatus: function (status) {
Expand Down Expand Up @@ -188,8 +173,6 @@ describe('Inferred Proxy Spans', function () {
})

it('should not create an API Gateway span if all necessary headers are missing', async () => {
await loadTest({})

await httpClient.get(`http://127.0.0.1:${port}/no-aws-headers`, {
headers: {}
})
Expand All @@ -213,8 +196,6 @@ describe('Inferred Proxy Spans', function () {
})

it('should not create an API Gateway span if missing the proxy system header', async () => {
await loadTest({})

// remove x-dd-proxy from headers
const { 'x-dd-proxy': _, ...newHeaders } = inferredHeaders

Expand Down Expand Up @@ -242,9 +223,54 @@ describe('Inferred Proxy Spans', function () {
})

describe('with configuration', function () {
it('should not create a span when configured to be off', async () => {
await loadTest({ inferredProxyServicesEnabled: false })
beforeEach(async () => {
const options = {
inferredProxyServicesEnabled: false,
service: 'aws-server'
}

// we can't force re-init the tracer, so we have to set the config manually
const tracer = require('../../dd-trace').init(options)
tracer._tracer._config.inferredProxyServicesEnabled = false

await agent.load(
['http', 'dns', 'net', 'aws-apigateway'],
[{ client: false }, { enabled: false }, { enabled: false }, { enabled: true }],
options
)

http = require('http')

const server = new http.Server(async (req, res) => {
controller && await controller(req, res)
if (req.url === '/error') {
res.statusCode = 500
res.end(JSON.stringify({ message: 'ERROR' }))
} else {
res.writeHead(200)
res.end(JSON.stringify({ message: 'OK' }))
}
})

// Force close connections when server closes
const connections = new Set()
server.on('connection', (connection) => {
connections.add(connection)
connection.on('close', () => {
connections.delete(connection)
})
})

return new Promise((resolve, reject) => {
appListener = server.listen(0, '127.0.0.1', () => {
port = server.address().port
appListener._connections = connections
resolve()
})
})
})

it('should not create a span when configured to be off', async () => {
await httpClient.get(`http://127.0.0.1:${port}/configured-off`, {
headers: inferredHeaders
})
Expand Down
Loading
Loading